2012-08-08 58 views
1

我有一个名为MyItems的实体表,并且此表中的每个项目都有一个到另一个表的外键。我想简单地通过我的项目环和访问字符串每个项目的外键对象的“名称”属性,像这样:在实体循环时实体框架异常(使用ToList()时工作)虽然)

foreach (var myItem in (from q in context.MyItems select q)) 
{ 
    string testName = myItem.ForeignItem.Name 
} 

当我这样做,ForeignItem是空的,我得到一个InvalidOperationException时我试图访问ForeignItem:

已经有一个打开的DataReader与此命令相关联,其中 必须先关闭。

然而 - 如果我不是调用ToList()像这样:

(from q in context.MyItems select q).ToList() 

我的外键对象来填充就好了。我意识到ToList()将会很昂贵,因为整个表将立即被检索。我怀疑在延迟加载的背后有什么问题,但我正在理解,它应该应该的工作,而不要求ToList()

我忽略了什么吗?

编辑:我在想也许使用var是造成问题的,所以我尝试使用

foreach (MyItem myItem in (from q in context.MyItems select q)) 
{ 
    // loop contents 
} 

代替 - 相同的结果。 myItem的属性填充,但外键对象保持为空。

编辑#2:我只在整个应用程序中使用一个对象上下文和一个Linq-to-Entities语句,所以我无法解释其他DataReader在何处运行。我还应该注意到,这个错误发生在循环中的第一个对象,所以它不是被检索的前一个项目的结果。

+0

是ForeignItem.Name需要加载的东西吗? – Brian 2012-08-08 18:40:29

+0

你试过把myItem.ForeignItem.Load();实际尝试获取ForeignItem.Name值之前? – Thousand 2012-08-08 18:43:10

+0

@Brian它应该加载,期间。为什么它在我调用'ToList()'的时候起作用,但当我不调的时候不是最大的问题。 – 2012-08-08 18:43:26

回答

5

你写了myItem而不是q。你应该使用这个:

(from q in context.MyItems select q) 

或者更简单地说,你可以这样写:

context.MyItems 

关于你更新的问题,这似乎是因为你之前先启动一个新的查询已经完成执行。可能的解决方案:

  • 当您运行原始查询时包含子项目。

    foreach (var myItem in context.MyItems.Include("ForeignItem")) { ... } 
    
  • 启用MultipleActiveResultSets。

相关

+0

我正在为我的对象名称进行消毒处理,错字与问题无关。我已经更新了问题中的代码。 – 2012-08-08 18:31:34

+0

是否还存在延迟执行问题? IIRC,LINQ查询推迟执行,直到他们通过类似于ToList/ToArray的方式执行。 ForEach是否会执行? – 2012-08-08 18:32:01

+1

@ kevinmajor1是的,'foreach'会强制执行。 – Servy 2012-08-08 18:37:02

0

这里就是我终于实现了,按照马克的建议,使用Include()

(from q in context.MyItems.Include("ForeignItemOne").Include("ForeignItemTwo").Include("ForeignItemThree") select q) 

顺便说一句,设置MultipleActiveResultSets为真也有效。现在,我将使用Include(),因为应用程序很小,并且只有一条Linq语句。