目录
一、异常 The ObjectContext instance has been disposed and can no longer be used for operations that require a connection
遇到这种问题的原因,是EF连接被释放了,然后操作导航属性【而导航属性又去读取数据库值】导致出现“连接已经释放的异常”解决办法如下
1.将导航属性改为“非延迟加载”
Person p;
using (var context = new MyDbContext())
{
//Include(x=>x.Dogs) 设置 Dogs 这个导航属性是“非延迟加载”的,直接将数据JOIN起来全部在一个查询中返回
p = context.Persons.Include(x => x.Dogs).First();
}
Console.WriteLine(string.Join(",", p.Dogs.Select(x => x.Name)));
2.将属性先在连接未释放前查询出来
Person p;
ICollection<Dog> Dogs;
using (var context = new MyDbContext())
{
p = context.Persons.First();
Dogs = p.Dogs;//在连接未关闭前先将导航属性查询出来
}
Console.WriteLine(string.Join(",", Dogs.Select(x => x.Name)));
//这样也可以使用了,导航属性“延迟加载”实现逻辑其实就是:
//在调用导航属性的get方法时:之前查询出值了?[返回之前查询的值]:[查询数据库值并存入之前查询值变量中]
Console.WriteLine(string.Join(",", p.Dogs.Select(x => x.Name)));
二、InvalidOperationException: 已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。
遇到这个异常的原因是因为:ADO.NET里面默认不允许在一个连接中,在上一个DataReader未关闭前打开新的DataReader进行读取数据!出现两个DataReader的原因也是因为导航属性的延迟加载,导致在遍历的过程中向数据库发送了查询请求并读取查询的数据导致的,解决办法如下:
1.设置导航属性为“非延迟加载”
using (var context = new MyDbContext())
{
//Include(x => x.Dogs) 设置 Dogs这个导航属性为非延迟加载的
foreach (var person in context.Persons.Include(x => x.Dogs))
{
Console.WriteLine("姓名:{0},拥有的狗:{1}", person.Name,
string.Join(",", person.Dogs.Select(x => x.Name)));
}
}
2.先将主查询全部查询完毕后再进行遍历
using (var context = new MyDbContext())
{
//ToList()是先将当前查询查询返回成List<Person>集合后再进行遍历处理
//ToList()操作结束后就会关闭查询的DataReader对象
//因为下面的操作是单线程的操作所以在加载导航属性时候也不会出现在上一个DataReader未关闭前就打开下一个DataReader的情况
foreach (var person in context.Persons.ToList())
{
Console.WriteLine("姓名:{0},拥有的狗:{1}", person.Name,
string.Join(",", person.Dogs.Select(x => x.Name)));
}
}
3.设置连接类型为支持在一个连接下有多个同时运行的DataReader此操作只支持SqlServer 2005以后的版本
MultipleActiveResultSets=true