建议避免将Entity查询结果直接当IEnumerable使用
2011-05-12 22:34 落小呆 阅读(3232) 评论(21) 编辑 收藏 举报使用Entity Framework查询当然是必不可少的,但有时不小心可能很简单的查询也会导致异常。
下面用EF4.1做个示例简单演示下异常发生的场景:
1: using (var context = new DemoContext())
2: {
3: var users = context.Users.AsEnumerable();
4: foreach (var user in users)
5: {
6: //其他查询逻辑
7: var test = context.Users.FirstOrDefault();
8: }
9: }
逻辑比较简单,就是首先查询一个User列表,并当作IEnumerable<User>对象进行读取的时候,在里面再进行查询操作,不出意外的话,程序会毫不留情的报错:
已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。
用Reflector查看OjbectQuery对象的GetEnumerator方法,不难找出异常的原因:由于Entity在读取数据的时候使用的是DbDataReader进行读取,当作为IEnumuerable<T>对象MoveNext进行操作时,只是使用DbDataReader进行一次Read操作,因此当查询的结果未完全读取完的时候,数据库连接一直被占用,当再次进行查询操作时便回出现上面的异常。
至于解决方案,网上很容易就能找到:
- 一种方案就是在数据库连接串中设置MultipleActiveResultSets=True,但需要注意的是该方案只适合Sql Server 2005以及以上版本,所以什么Sql Server 2000之类设置也没用。
- 还一种方案就比较直接,别用什么AsEnumerable之类(直接将查询结果丢进foreach),尽量使用ToArray、ToList方法,什么说Entity用ToList方法会有效率问题啥的,别乱说先,Reflector很好用的,看看源代码先,别随便整个测试啥的就说Entity这样慢那样不行。