我将 EF 5 与 Web 窗体 (ASP.NET 4.5) 一起使用,采用“每个请求一个 DbContext 实例”的方法。
但是这种情况有点复杂:我有一个多步骤的创建/编辑屏幕,我将当前实体存储在 Session 中,然后我对其进行操作,在最后一步中,我将其提交到数据库。
创建一个新实例很好,但我无法终生编辑现有实体......因为这是另一个请求,我原来的 DbContext 实例丢失了,当我将它附加到一个新实例时,我得到了一个实体对象不能被多个 IEntityChangeTracker错误实例引用。
我的代码太复杂了,无法在这里发布,但我会尝试准确地总结一下:
我的数据库上下文:
public class AppContext : DbContext
{
// DbSet declarations...
public static AppContext Current {
get { var context = HttpContext.Current.Items["Contexts.AppContext"] as AppContext;
if (context == null)
{
context = new AppContext();
HttpContext.Current.Items["Contexts.AppContext"] = context;
}
return context;
}
}
}
页面代码的示例:
protected void Page_Load(object sender, EventArgs e)
{
int? id = null; // After this, I try to get it from the QueryString, parse it, etc.. Omitted for sake of brevity
// If I have an ID, it means I'm editing...
Session["Product"] = id.HasValue ? new Product() : AppContext.Current.Products.Find(id));
MethodToPopulateFields(); // Internally, it uses the Session variable
}
protected void Step1(){ // through n
// Manipulates the Session["Product"] based on page input...
}
protected void Save(){
var product = Session["Product"] as Product;
if(product.ID == 0)
product = AppContext.Current.Products.Add(product);
// throws an exception:
// AppContext.Current.Entry(product).State = EntityState.Modified;
// this too:
// AppContext.Products.Attach(product);
AppContext.Current.SaveChanges();
}
我知道我可以从数据库中获取旧实体,手动更新并保存,所有这些都在最后一步,但我真的不想这样做......
谢谢你。