ASP.NET MVC 2で、Entity Framework 4を使用すると、「エンティティオブジェクトをIEntityChangeTrackerの複数のインスタンスで参照できません」というエラーが発生します。
SOを検索すると、HttpContextごとに1つのObjectContextインスタンスのみである必要があるのに、EntityFrameworkObjectContextのインスタンスが異なることが原因である可能性があります。
私はまさにそれをしているように見えるこのコード(私が参加するずっと前に書かれた)を持っています-すべてのHttpContextに対して1つのObjectContextを持っています。しかし、「IEntityChangeTracker」例外が頻繁に発生するため、意図したとおりに機能していない可能性があります。
// in ObjectContextManager.cs
public const string ConnectionString = "name=MyAppEntities";
public const string ContainerName = "MyAppEntities";
public static ObjectContext GetObjectContext()
{
ObjectContext objectContext = GetCurrentObjectContext();
if (objectContext == null) // create and store the object context
{
objectContext = new ObjectContext(ConnectionString, ContainerName);
objectContext.ContextOptions.LazyLoadingEnabled = true;
StoreCurrentObjectContext(objectContext);
}
return objectContext;
}
private static void StoreCurrentObjectContext(ObjectContext objectContext)
{
if (HttpContext.Current.Items.Contains("EF.ObjectContext"))
HttpContext.Current.Items["EF.ObjectContext"] = objectContext;
else
HttpContext.Current.Items.Add("EF.ObjectContext", objectContext);
}
private static ObjectContext GetCurrentObjectContext()
{
ObjectContext objectContext = null;
if (HttpContext.Current.Items.Contains("EF.ObjectContext")
objectContext = (ObjectContext)HttpContext.Current.Items["EF.ObjectContext"];
return objectContext;
}
私はこのコードを調べましたが、正しいように見えます。HttpContextごとに1つのObjectContextインスタンスを返すように指示できる限り、これは実行されます。コードは間違っていますか?
コードが間違っていない場合、「エンティティオブジェクトはIEntityChangeTrackerの複数のインスタンスで参照できません」という例外が発生するのはなぜですか?
編集:ObjectContextがどのように破棄されるかを示すには:
// in HttpRequestModule.cs
private void Application_EndRequest(object source, EventArgs e)
{
ServiceLocator.Current.GetInstance<IRepositoryContext>().Terminate();
}
// in RepositoryContext.cs
public void Terminate()
{
ObjectContextManager.RemoveCurrentObjectContext();
}
// in ObjectContextManager.cs
public static void RemoveCurrentObjectContext()
{
ObjectContext objectContext = GetCurrentObjectContext();
if (objectContext != null)
{
HttpContext.Current.Items.Remove("EF.ObjectContext");
objectContext.Dispose();
}
}