EntityFramework是否会保持连接开启?

6
我有一个问题,我的应用通过EF连接到数据库时,这些连接会在我不希望它们存在的情况下保持打开状态。我正在为体育赛事创建计时系统,并动态创建新数据库,复制现有的DB文件并使用根据需要构建的正确文件名的连接字符串进行附加。
一种创建新文件的方法是基于现有事件,即复制然后清除大量数据。如果我在加载现有事件时尝试执行此操作,则无法复制该文件,因为SQL Server已将其锁定,并且我不能显式分离它,因为SQL Server声称它正在使用中。当我查看sys.sysprocesses的内容时,我发现EF仍然维护着“AWAITING COMMAND”的连接,尽管我将所有内容都封装在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进程,并在文件操作后重新启动它。这似乎既沉重又危险。有人能建议更礼貌的选项吗?
2个回答

6

你遇到了与SQL连接池有关的问题。这是默认情况下为了优化性能而进行的操作。即使你调用Dispose和Close关闭该SqlConnection对象,SqlConnection仍然会被保留。 要禁用连接池,你需要在连接字符串中将pooling设置为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
正如提到的那样,这是因为您开启了连接池,这通常是一个好的选择,因为创建连接是很昂贵的。您有两个选项:
  1. 在连接字符串中关闭连接池,连接将不会添加到池中。请注意,如果在代码或应用程序之外进行连接,则可能仍存在其他连接。
  2. 执行SqlConnection.ClearPool以清除连接池并解锁本地数据库文件。
有关 SQL Server 连接池的更多信息,请参见此文章:SQL Server Connection Pooling (ADO.NET)

谢谢。没有标记为答案,因为Viru先回答了,但额外的信息很有用。 - Craig Graham
@CraigGraham - 很高兴能帮忙。别担心,世界上只有一个 - Igor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接