EF導航屬性使用常見異常

一、異常 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章