实体框架保持连接打开
本文关键字:连接 框架 实体 | 更新日期: 2023-09-27 18:36:22
我有一个问题,即通过 EF 从我的应用程序连接到数据库,当我不希望它们打开时,它们处于打开状态。我正在为体育赛事做一个计时系统,并动态创建新数据库,复制现有数据库文件并使用根据需要使用正确文件名生成的连接字符串附加它们。
创建新文件的一种方法是将其基于现有事件,即复制然后清除数据负载。如果我在加载现有事件时尝试此操作,则无法复制该文件,因为 SQL Server 已将其锁定,并且由于 SQL Server 声称它正在使用中,因此无法显式分离它。当我查看 sys.sysprocesses 的内容时,我发现是的,EF 正在维护"等待命令"的连接。尽管我将所有内容包装在 using() 构造中并使用 IDbConnectionInterceptor 来确认我的连接正在被释放。
我设法将一个例子分解为
using (SportsTimerEntities ctx = new SportsTimerEntities("metadata=res://*/DataModel.csdl|res://*/DataModel.ssdl|res://*/DataModel.msl;provider=System.Data.SqlClient;provider connection string='"Data Source=(LocalDB)''v11.0;AttachDbFilename=C:''Work''SportsTimer''Events''559eae6a-9974-4463-8546-00824b4aad23.mdf;Integrated Security=True;MultipleActiveResultSets=True;Connect Timeout=30;Application Name=EntityFramework'""))
{
dbDevices = ctx.Devices.ToList();
}
在using()
块之前没有连接。块退出后,连接仍然存在。尽管 IDbConnectionInterceptor 确认Dispose()
已被调用。
目前,我能想到的释放文件的唯一方法是找到并杀死sqlservr进程,并在执行文件操作后让它重新启动。这似乎既沉重又危险。谁能提出更礼貌的选择?
由于 SQL 连接池,您正面临问题。默认情况下,这样做是为了优化性能。SQlConnection 将保持不变,即使您在该 SqlConnection 对象上调用 Dispose and Close。若要禁用池化,必须在连接字符串中将池化添加到 false
using (SportsTimerEntities ctx = new SportsTimerEntities(
@"metadata=res://*/DataModel.csdl|res://*/DataModel.ssdl|res://*/DataModel.msl;
provider=System.Data.SqlClient;
provider connection string=""Data Source=(LocalDB)''v11.0;
AttachDbFilename=C:''Work''SportsTimer''Events''559eae6a-9974-4463-8546-00824b4aad23.mdf;
Integrated Security=True;
Pooling=false;
MultipleActiveResultSets=True;
Connect Timeout=30;
Application Name=EntityFramework"""))
{
dbDevices = ctx.Devices.ToList();
}
如前所述,这样做是因为您打开/启用了连接池,这通常是一件好事,因为创建连接的成本很高。您有 2 个选项。
- 关闭连接字符串中的连接池,连接不会添加到池中。请注意,如果在该代码段或应用程序之外建立连接,则其他连接可能仍然存在。
- 执行 SqlConnection.ClearPool,这将清除连接池并解锁您的本地数据库文件。
连接池的详细信息,请参阅此文章 SQL Server 连接池 (ADO.NET)。