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を使用する必要があります。何が問題ですか?
コンテキストは別の場所(表示したコードではない)に配置されているため、基本的にRegister
アクションからコンテキストにアクセスすると、例外がスローされます。
実際には、コンテキストにアクセスするために静的シングルトンを使用するべきではありません。 リクエストごとに新しいDbContext
インスタンスをインスタンス化します。 マルチスレッドサーバーでEntity Frameworkを操作するc# を参照してください。
私の場合、GetAllメソッドはラムダ式のwhere句の後にToList()メソッドを呼び出していませんでした。 ToList()を使用した後、私の問題は解決しました。
Where(x => x.IsActive).ToList();
登録ビューでUser
のナビゲーションプロパティを「遅延読み込み」している可能性があります。ビューに送信する前に、Include
でDbSet
メソッドを使用して含めるようにしてください。
_db.Users.Include(u => u.PropertyToInclude);
また、静的プロパティとDbContext
sを共有すると、予期しない副作用が発生する可能性があります。
私は以前同じ問題を抱えていました。上で述べたように解決しました。コンテキストの新しいインスタンスをインスタンス化します。
これを使用してみてください:
using (HotelContextProductStoreDB = new ProductStoreEntities())
{
//your code
}
このようにして、コードを使用するたびに新しいインスタンスが作成され、コンテキストが破棄されることはありません。
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;
}
}
}
たぶん、オプションになることができます。