前言
本節我們來探讨到底需不需要在連接配接字元串上加上MultipleActiveResultSets = true ?,若您有更深層次的了解歡迎留下您的腳印。
EntityFramework 6.x和EntityFramework Core需要MultipleActiveResultSets?
很多童鞋遇到如下圖中錯誤就立馬想到在連接配接字元串上加上 MultipleActiveResultSets = true ,但是這樣真的是最終解決方案麼?

下面我們來看一段在EntityFramework 6.x中的代碼,示範如上問題的出現。
using (var ctx = new EfDbContext()) { ctx.Database.Log = Console.WriteLine; var customers = ctx.Customers; foreach (var customer in customers) { ctx.Entry(customer).Collection(d => d.Orders).Load(); } };
當您在EntityFramework 6.x中運作上述代碼就會抛出如上圖異常(不要關心上述代碼是否合理,或許您可能說直接使用顯式加載對吧,如上代碼旨在引出問題)。然後我們在連接配接字元串上如下加上一句就可以解決問題。
connectionString="Data Source=WANGPENG;Initial Catalog=EntityFramework6;Integrated Security=true;MultipleActiveResultSets=True;"
我們知道MultipleActiveResultSets即MARS在SQL Server2005中被引入,意為單連接配接多請求,但是它非線程安全,在我看來這個特性在ADO.NET中可能非常适用,但是在EntityFramework 6.x中作用不大,雖然如上可以從資料庫連接配接層面來解決問題,大部分這種情況的出現還是因為代碼寫的有問題,我們直接調用ToList即可,如下:
using (var ctx = new EfDbContext()) { ctx.Database.Log = Console.WriteLine; var customers = ctx.Customers.ToList(); foreach (var customer in customers) { ctx.Entry(customer).Collection(d => d.Orders).Load(); } };
我們知道ToList是最終翻譯成SQL語句請求資料庫傳回對應資料,即通過ToList既可以打開連接配接也可以關閉連接配接,當我們不用ToList時,此時打開了一個連接配接,同時已經有了一個DataReader,接下來周遊時則再會在Command上打開一個DataReader加載Orders,此時就會抛出第一個DataReader未關閉的情況,大部分出現這樣的一樣我們都可以通過ToList來解決,當然也可以用延遲加載(關于EF 6.x中延遲加載請謹慎适用,我在我的書中《你必須掌握的EntityFramework 6.x與Core 2.0》中也有講到,除非您明确自己會正确使用)和顯式加載來解決。那在EntityFramework Core中是否運作上述同樣代碼會抛出異常,然後我們需要在連接配接字元串上加上此特性呢?我們來看看。
using (var context = new EFCoreDbContext()) { var blogs = context.Blogs; foreach (var blog in blogs) { context.Entry(blog).Collection(p => p.Posts).Load(); } }
通過如上圖我們知道完全不會如EntityFramework 6.x中抛出異常,這點有所不同。大部分情況下,出現如上異常或許可能是代碼寫的問題,不一定非得要加上 MultipleActiveResultSets=True;
總結
本文沒有深入探讨文章标題,若您有抛出如上異常非得加上MultipleActiveResultSets=True才能解決問題,請留下您的評論,讓我繼續深入學習,在此表示感謝。接下來我會繼續探讨和對比EntityFramework 6.x和EntityFramework Core中不為人知的秘密,同時也會陸續更新EF Core 2.1并深入探讨。
所有的選擇不過是為了下一次選擇做準備