“已经有一个与此命令关联的开放式数据加载器” - 即使使用Include()

时间:2013-08-05 06:44:12

标签: linq asp.net-mvc-4 entity-framework-5

我正在尝试加载所有Dish个对象。 DishDishImage具有一对多的关系,即Dish可以有多个DishImage与之关联。

以下是这两个类的代码。

  1. Dish
  2. DishImage
  3. 这就是我尝试在动作方法中检索它的方法:

        [ChildActionOnly]
        public PartialViewResult TopDishes()
        {
            IEnumerable<Dish> topDishes = dishRepository.Dishes.Include( d => d.DishImages );                                                        
            return PartialView(topDishes);
        }
    

    以下是视图的代码:

      @model IEnumerable<RestaurantHub.Domain.Entities.Dish>
    
     @foreach (var dish in Model)
     {
        <div class="top-ten-offers-list">
    
          <div class="top-ten-offer">
            <p class="top-ten-deal-description">
                @dish.Description
            </p>
    
            <img src="@dish.DishImages.First().ImagePath" />
            <p class="top-ten-deal-title">@dish.Name</p>
         </div>
    
       </div>
    }
    

    我已经阅读了几个SO问题,大多数人建议使用Include()(我正在做),其他人建议将MARS设置为true。我相信我在这里错过了一些微妙的观点。任何帮助表示赞赏。

    调试信息:

    如果我将代码调试到action方法,我可以验证(通过枚举结果)正在加载正确的数据。但是当控件在视图中达到foreach循环时,它会抛出上述错误。

    如果我从视图中删除行@dish.DishImages.First().ImagePath它可以正常工作,但我没有得到任何图像。

    Debug view of Result Set

2 个答案:

答案 0 :(得分:6)

那是因为您同时有多个查询:

... 当Code First创建连接时 惯例,它在我们的例子中,它将启用MARS。如果你供应 如果您愿意,您需要确保启用MARS 能够有多个活动查询。

如果您未启用MARS,并且您的代码尝试运行两个活动查询,您将收到 一个例外。您收到的异常将取决于触发该操作的操作 第二个查询,但内部异常将是一个InvalidOperationException说明 “已经有一个与此命令关联的开放DataReader必须是 首先关闭。“ - from Julia Lerman's Programming EF DbContext

您似乎已在web.config中创建了自己的EF连接。如果是,则应将MultipleActiveResultSets=True;添加到其connectionString媒体资源中:

<add name="..." connectionString="metadata=res:...;provider=System.Data.SqlClient;provider connection string=&quot;data source=... ;
MultipleActiveResultSets=True; //Add this
App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

<强>更新

事实上,问题出在你看来。 <img src="@dish.DishImages.First().ImagePath" />行导致该异常。你问为什么?!我会告诉你原因:

首先,您在db上执行了查询:

IEnumerable<Dish> topDishes = dishRepository.Dishes.Include( d => d.DishImages );                                                        
return PartialView(topDishes);

但是,实际上你没有执行任何查询!你刚刚创建了一个IEnumerable集合(那是因为你没有调用.ToList().AsEnumerable()等),这不是问题。

所以你将一个集合传递给你的视图。第一个查询在foreach循环中执行 - 好的,仍然没有问题......

在我们转到img标记之前:<img src="@dish.DishImages.First().ImagePath" />。这个(@dish.DishImages.First())对db执行新查询 - &gt;问题!

<强>解决方案:

我不知道在您的控制器中调用.ToList()可以解决您的问题 - 也许。但是,您当前的EF连接字符串必须具有MultipleActiveResultSets=True;属性才能在这些情况下正常工作。

答案 1 :(得分:1)

您使用IEnumerable并且未将您的收藏集实现为List / Array的原因是否有任何正当理由?我认为你的问题会消失,如果你将所有结果都记在内存中(ToList() / ToArray()),然后将它们交给你可以操作内存中集合的视图,但是你觉得合适