DbContext был удален

Я разработал веб-приложение с ASP.NET MVC 4 и SQL Server 2008, я создаю класс ContextManager, чтобы иметь только один контекст базы данных на всех страницах.

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;
        }
    }
}

Он работает должным образом на большинстве страниц, но на странице регистрации что-то идет не так, и мой контекст удален со следующей ошибкой:

Операция не может быть завершена, так как DbContext был удален.

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 );

на линии _db.Contacts.Add( contact ); Я получил исключение.

Но без использования ContextManager путем изменения

HotelContext _db = ContextManager.Current;

в:

HotelContext _db = new HotelContext();

проблема была решена. Но мне нужно использовать свой собственный ContextManager. В чем проблема?

4 ответа

Решение

Ваш контекст был размещен где-то еще (не в коде, который вы показали), поэтому, в основном, когда вы получаете к нему доступ из своего Register действие, оно бросает исключение.

На самом деле, вы не должны использовать статический синглтон для доступа к вашему контексту. Сделать экземпляр нового DbContext экземпляр для каждого запроса. См. C# работа с Entity Framework на многопоточном сервере

В моем случае мой метод GetAll не вызывал метод ToList() после предложения where в лямбда-выражении. После использования ToList() моя проблема была решена.

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

Вы, вероятно, 'ленивая загрузка' свойства навигации User в вашем представлении регистрации. Убедитесь, что вы включили его с помощью Include метод на вашем DbSet перед отправкой на просмотр:

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

Также делимся DbContexts со статическим свойством может иметь неожиданные побочные эффекты.

Зачем переопределять Dispose(bool)?

public partial class HotelContext : DbContext
{
    public bool IsDisposed { get; set; }
    protected override void Dispose(bool disposing)
    {
        IsDisposed = true;
        base.Dispose(disposing);
    }
}

Затем проверьте IsDisposed

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.IsDisposed)
            {
                context = new HotelContext();
                HttpContext.Current.Items[key] = context;
            }
            return context;
        }
    }
}

Может быть, может быть вариант.

Раньше у меня была такая же проблема. Я решил это, как было сказано выше. Создайте новый экземпляр вашего контекста.

Попробуйте использовать это:

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

Таким образом, каждый раз, когда вы будете использовать свой код, будет создаваться новый экземпляр, и ваш контекст не будет уничтожен.

Другие вопросы по тегам