2011-05-11 64 views
3

我建立一个ASP.NET MVC 3应用程序,我已经有了一个模型,看起来像这样:错误显示的详细信息(例如ObjectContext的已配置)

public partial class Flavor 
{ 
    // ... 
    public string Name { get; set; } 
    public bool HasNuts {get; set; } 
    public virtual ICollection<SaleData> Sales {get; set;} 
    // ... 
} 

从一个获取一些数据DB这样:

public PartialViewResult Details(int id) 
{ 
    using (var db = new IceCreamDBFlavors()) 
    { 
     Flavor someFlavor = db.Flavors.Find(id); 
     someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList(); 
     return PartialView("details", someFlavor);  
    } 
} 

在视图上我做这样的事:

<fieldset> 
    <legend>Sales Data</legend> 
    @foreach (var sale in Model.Sales) 
    { 
     <div>Weekly</div> 
     <div>@sale.Weekly</div> 
    } 
</fieldset> 

如果我不获取销售数据,我的Flavor数据显示正常,没有错误,但添加调用以检索销售数据列表会导致错误“ObjectContext实例已被处置,不能再用于需要连接的操作。”发生。

我读了一些关于此的其他文章,并猜测我错过了这里的东西。我相信这个错误是由于懒惰加载,至少根据我在这里和其他地方阅读的内容。在返回PartialView并检查对象之前,在Controller中设置一个断点,我相信会导致评估发生,因此所有内容都按照我的意愿显示。

我的印象是,ToList()调用会强制Sales集合被填充。由于我没有问题,当该行被注释掉时,我认为问题仍然与此相关,当View正试图迭代销售,它不能。我在这里纠正?我想我想到我正在强制评估。我该如何解决这个问题?

回答

0

不要处理从ObjectContext继承的IceCreamDBFlavors类,它需要具有比当前允许的更大的生命周期。

变化

using (var db = new IceCreamDBFlavors()) 
{ 
    Flavor someFlavor = db.Flavors.Find(id); 
    someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList(); 
    return PartialView("details", someFlavor);  
} 

try 
{ 
    var db = new IceCreamDBFlavors(); 

    Flavor someFlavor = db.Flavors.Find(id); 
    someFlavor.Sales = db.Sales.Where(c => c.FlavorID == id).ToList(); 
    return PartialView("details", someFlavor);  
} 
catch(Exception ex) 
{ 
    // log exeption 
} 
+0

谢谢!这解决了这个问题。我想我需要重新检查*为什么IceCreamDBFlavors需要更长的使用寿命。 – itsmatt

+0

@itsmatt没问题,这一个也抓到我了。它需要更长的生命周期,因为现有的using语句处理了对象上下文,稍后在相同的请求中(在视图中),延迟加载需要再次使用对象上下文深入到数据中。您可以在请求结束时使用一些处理对象上下文的逻辑。 – Swaff

+1

不,不,不,这是不好的,以及永远不应该将它变成生产系统的代码类型!你基本上说在视图中运行SQL是可以的,并且打开SELECT N + 1问题的所有可能性。 – jfar

2

我怀疑是Flavor有其他集合(不只是Sales),它实际上是在访问这些,它打破的时间。

在这里,您仅替换Sales,而其他集合或复杂属性仍然需要对象上下文。