恰当的处理EF中的ObjectContext或是NHibernate session
2011-06-26 18:42 Zhang_Chen 阅读(1250) 评论(4) 编辑 收藏 举报在使用各个ORM框架的时候,我们不免都会碰到这样的一些问题
- 当我们希望使用延迟加载时ObjectContext已经被释放了
- Attach一个实体时被告知不能被多个IEntityChangeTracker引用
例如下面的情况
namespace Demo.Business { public class BPerson { public static void DoSomething(Person p) { p.Age++;//这里我们进行一些修改 var db = new Entities(); db.Person.Attach(p); db.ObjectStateManager.ChangeObjectState(p, EntityState.Modified); db.SaveChanges(); } ....... //PeopleController.cs [HttpPost] public ActionResult Edit(Person person) { if (ModelState.IsValid) { Business.BPerson.DoSomething(person); var db = new Entities(); db.Person.Attach(person);//这里会抛出异常 db.ObjectStateManager.ChangeObjectState(person, EntityState.Modified); db.SaveChanges(); return RedirectToAction("Index"); } return View(person); }
显然解决的办法就是使用同一个ObjectContext的实例,
但是还有需要注意的一点:我们什么时候实例化它,怎么样得到它的引用又什么时候释放它?
我想到了
HttpContext.Items
我们可以方便的在程序的各个位置获得它的引用,于是上面的代码稍加修改:
public static void DoSomething(Person p) { p.Age++; var db = GetDB(); db.Person.Attach(p); db.ObjectStateManager.ChangeObjectState(p, EntityState.Modified); db.SaveChanges(); } public static Entities GetDB() { var db = HttpContext.Current.Items["KEY_DB"] as Entities; if (db == null) { db = new Entities(); HttpContext.Current.Items["KEY_DB"] = db; } return db; }
[HttpPost] public ActionResult Edit(Person person) { if (ModelState.IsValid) { Business.BPerson.DoSomething(person); var db = Business.BPerson.GetDB(); db.Person.Attach(person); db.ObjectStateManager.ChangeObjectState(person, EntityState.Modified); db.SaveChanges(); return RedirectToAction("Index"); } return View(person); }
看起来不错。剩下释放的问题。
我们希望在整个http请求中使用同一个ObjectContext实例,所以就在请求结束的时候释放吧,像这样
public static Entities GetDB() { var db = HttpContext.Current.Items["KEY_DB"] as Entities; if (db == null) { db = new Entities(); HttpContext.Current.Items["KEY_DB"] = db; HttpContext.Current.ApplicationInstance.EndRequest += DisposeDB; } return db; } private static void DisposeDB(object sender,EventArgs e) { if (HttpContext.Current.Items.Contains("KEY_DB")) { var context = HttpContext.Current.Items["KEY_DB"] as Entities; if (context != null) context.Dispose(); } }
或者你可以将实例化和释放都放到Global.asax.cs中。
希望对你有帮助