項目中類似於以下的代碼,實際的代碼要更復雜,DbContext
是依賴注入的:
報錯如下:
This MySqlConnection is already in use. See https://fl.vu/mysql-conn-reuse
錯誤提示就是MySqlConnection
在使用了。分析了代碼,沒覺得有什么問題。
網上搜了不少,針對這個問題也是很少:
粗略的看了一下,感覺和我的問題關系不大。
后來看到這句代碼,會不會是沒有使用ToList()
的原因:
var menus = db.Menus.Select(a => a.Name);
果然加上ToList()
后沒有異常了!。
為什么呢?
Select()
是延遲加載,在foreach
是向數據庫讀取數據,為什么讀取出來后執行SaveChanges()
會報錯呢?
在這篇文章Connection Reuse找這段代碼:
using (var connection = CreateOpenConnection())
using (var command = new MySqlCommand("SELECT id FROM ...", connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var idToUpdate = reader.GetValue(0);
connection.Execute("UPDATE ... SET ..."); // don't do this
}
}
在打開MySqlDataReader
時是不能進行操作的。
foreach
進行從數據讀取menus
時也進行了讀操作,這個讀操作是不是用了MySqlDataReader
呢?。
以上是EF Core+MySql
實現的,EF Core+SqlServer
就不會有這樣的問題。
於是下載了Pomelo.EntityFrameworkCore.MySql
源碼進行調試。
還是沒找到什么答案。
Pomelo.EntityFrameworkCore.MySql
是構建在MySqlConnector
之上的,MySqlConnector
不熟悉沒有研究過,有機會再研究吧!
總結
var menus = db.Menus.Select(a => a.Name);
foreach (var item in menus)
foreach
執行延遲加載在EFCore+SqlServer
和EFCore+Mysql
的實現方式是不一樣的。
有可能像之前說的,在MySqlDataReader
讀取期間是不允許進行數據庫操作。