项目中类似于以下的代码,实际的代码要更复杂,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
读取期间是不允许进行数据库操作。