web-dev-qa-db-ja.com

DbContextは破棄されました

ASP.NET MVC4とSQLServer 2008を使用してWebアプリケーションを開発し、すべてのページに1つのデータベースコンテキストのみを持つように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を使用する必要があります。何が問題ですか?

7
Ali Esfahani

コンテキストは別の場所(表示したコードではない)に配置されているため、基本的にRegisterアクションからコンテキストにアクセスすると、例外がスローされます。

実際には、コンテキストにアクセスするために静的シングルトンを使用するべきではありません。 リクエストごとに新しいDbContextインスタンスをインスタンス化しますマルチスレッドサーバーでEntity Frameworkを操作するc# を参照してください。

9
ken2k

私の場合、GetAllメソッドはラムダ式のwhere句の後にToList()メソッドを呼び出していませんでした。 ToList()を使用した後、私の問題は解決しました。

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

登録ビューでUserのナビゲーションプロパティを「遅延読み込み」している可能性があります。ビューに送信する前に、IncludeDbSetメソッドを使用して含めるようにしてください。

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

また、静的プロパティとDbContextsを共有すると、予期しない副作用が発生する可能性があります。

2
Henk Mollema

私は以前同じ問題を抱えていました。上で述べたように解決しました。コンテキストの新しいインスタンスをインスタンス化します。

これを使用してみてください:

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

このようにして、コードを使用するたびに新しいインスタンスが作成され、コンテキストが破棄されることはありません。

1
GreatNews

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

たぶん、オプションになることができます。

0
antonio