2013-09-05 56 views
6

Tôi đã phát triển một ứng dụng web với ASP.NET MVC 4 và SQL Server 2008, tôi tạo ra lớp ContextManager chỉ có một bối cảnh cơ sở dữ liệu trong tất cả các trang.DbContext đã được xử lý

public static class ContextManager 
{ 
    public static HotelContext Current 
    { 
     get 
     { 
      var key = "Hotel_" + HttpContext.Current.GetHashCode().ToString("x") 
         + Thread.CurrentContext.ContextID.ToString(); 
      var context = HttpContext.Current.Items[key] as HotelContext; 
      if (context == null) 
      { 
       context = new HotelContext(); 
       HttpContext.Current.Items[key] = context; 
      } 
      return context; 
     } 
    } 
} 

Nó hoạt động đúng trong hầu hết các trang, nhưng trong đăng ký trang họ gặp khó khăn và bối cảnh của tôi đi lật đổ với lỗi sau:

The operation cannot be completed because the DbContext has been disposed.

public ActionResult Register (RegisterModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // Attempt to register the user 
     try 
     { 
      WebSecurity.CreateUserAndAccount(model.UserName, model.Password, 
               new 
               { 
                 Email = model.Email, 
                 IsActive = true, 
                 Contact_Id = Contact.Unknown.Id 
               }); 

      //Add Contact for this User. 
      var contact = new Contact { Firstname = model.FirstName, LastName = model.Lastname }; 
      _db.Contacts.Add(contact); 
      var user = _db.Users.First(u => u.Username == model.UserName); 
      user.Contact = contact; 
      _db.SaveChanges(); 
      WebSecurity.Login(model.UserName, model.Password); 

tại dòng _db.Contacts.Add(contact); tôi có ngoại lệ .

Nhưng mà không sử dụng ContextManager bằng cách thay đổi

HotelContext _db = ContextManager.Current; 

thành:

HotelContext _db = new HotelContext(); 

vấn đề đã được giải quyết. Nhưng tôi cần phải sử dụng ContextManager của riêng mình. Vấn đề là gì?

Trả lời

7

Ngữ cảnh của bạn đã được xử lý ở nơi khác (không phải trong mã bạn đã hiển thị), vì vậy về cơ bản khi bạn truy cập nó từ hành động Register của bạn, nó sẽ ném ngoại lệ.

Thực ra, bạn không nên sử dụng một singleton tĩnh để truy cập vào ngữ cảnh của bạn. Thực hiện một ví dụ DbContext mới cho mỗi yêu cầu. Xem c# working with Entity Framework in a multi threaded server

+0

sự cố xảy ra sau khi tạo người dùng và tôi cũng đã kiểm tra db của mình để chắc chắn, WebSecurity.CreateUserAndAccount đang tiến hành thành công nhưng tại _db.Contacts.Add (liên hệ); tôi có ngoại lệ. –

+1

@ ken2k, ContextManager đang lưu trữ DbContext trong HttpContext.Current.Items, vì vậy nó sẽ là một cá thể mới theo yêu cầu. – mendel

2

Có thể bạn đang 'tải chậm' thuộc tính điều hướng của User trong chế độ xem đăng ký của mình. Hãy chắc chắn rằng bạn bao gồm nó bằng cách sử dụng phương pháp Include trên DbSet của bạn trước khi gửi nó vào xem:

_db.Users.Include(u => u.PropertyToInclude); 

Ngoài ra, chia sẻ DbContext s với một tài sản tĩnh có thể có tác dụng phụ không mong muốn.

2

Trong trường hợp của tôi, phương thức GetAll của tôi không gọi phương thức ToList() sau mệnh đề where trong biểu thức lambda. Sau khi sử dụng ToList(), vấn đề của tôi đã được giải quyết.

Where(x => x.IsActive).ToList(); 
0

Tôi từng gặp vấn đề tương tự. Tôi đã giải quyết nó như đã nói ở trên. Khởi tạo một trường hợp mới của ngữ cảnh của bạn.

Hãy thử sử dụng này:

  using (HotelContextProductStoreDB = new ProductStoreEntities()) 
      { 
       //your code 
      } 

Bằng cách này nó sẽ tạo ra một trường hợp mới mỗi khi bạn sử dụng mã của bạn và hoàn cảnh của bạn sẽ không được xử lý.