获取含主分类信息的子分类列表遇ObjectDisposedException错误求助
解决MVC中ObjectContext已释放的导航属性访问问题
嘿,这个问题我之前也碰到过!你遇到的System.ObjectDisposedException其实是Entity Framework延迟加载的典型坑,我来给你拆解下原因和解决办法:
问题根源
你在Controller里用using块包裹了EF上下文,当代码执行完return View()后,db对象就被自动释放了。但在View里你尝试访问item.Category.CategoryName这个导航属性——EF的延迟加载特性会在你第一次访问导航属性时才去数据库拉取关联数据,可这时候上下文已经被销毁,没法建立数据库连接,自然就报错了。
解决方案
方法一:用Include预先加载关联数据(推荐)
直接在查询SubCategories的时候,通过Include方法把关联的Category数据一起加载出来(也就是「急加载」),这样到View里的时候数据已经在内存里了,不需要再去数据库:
public ActionResult ProductCreate() { using (MyappWebDbEntities db = new MyappWebDbEntities()) { // 引用System.Data.Entity命名空间才能用lambda版本的Include ViewBag.SubCategories = db.SubCategories.Include(s => s.Category).ToList(); return View(); } }
如果你用的是较老的EF版本,也可以用字符串参数的Include:Include("Category"),不过lambda版本更安全,不会因为拼写错属性名出问题。
方法二:使用ViewModel封装所需数据(更规范的做法)
创建一个专门的ViewModel类,只包含View需要的字段,在Controller里就把数据组装好,避免在View里直接操作EF实体:
// 首先定义ViewModel类 public class SubCategoryViewModel { public int SubCategoryId { get; set; } public string SubCategoryName { get; set; } public string CategoryName { get; set; } } // 然后在Controller里组装数据 public ActionResult ProductCreate() { using (MyappWebDbEntities db = new MyappWebDbEntities()) { var subCategoryList = db.SubCategories .Select(s => new SubCategoryViewModel { SubCategoryId = s.SubCategoryId, SubCategoryName = s.SubCategoryName, CategoryName = s.Category.CategoryName }) .ToList(); ViewBag.SubCategories = subCategoryList; return View(); } }
View里的代码完全不用改,因为ViewModel的属性名和原实体一致,直接就能用。这种方式能让代码更清晰,还能避免很多EF相关的坑。
方法三:关闭延迟加载(不推荐)
你也可以手动关闭上下文的延迟加载,但这样所有导航属性都不会自动加载,除非你手动处理,所以一般不建议这么做:
public ActionResult ProductCreate() { using (MyappWebDbEntities db = new MyappWebDbEntities()) { db.Configuration.LazyLoadingEnabled = false; ViewBag.SubCategories = db.SubCategories.ToList(); // 注意:这时候item.Category会是null,所以还是得提前加载数据,不如直接用方法一 return View(); } }
内容的提问来源于stack exchange,提问作者Kevin himch
相关产品推荐
相关产品推荐

