我正在使用Linq to SQL并在博客文章中阅读有关尽快关闭数据库连接的信息。作为一个例子,他们展示了一个变量被转换为一个列表(使用.ToList())而不是实际返回Linq查询。我有以下代码:
public static bool HasPassword(string userId)
{
ProjDataContext db = new ProjDataContext();
bool hasPassword = (from p in db.tblSpecUser
where p.UserID == userId
select p.HasPassword).FirstOrDefault();
return hasPassword;
}
这个查询好吗?或者数据库连接是否会保持打开的时间超过必要的时间?
感谢您的任何建议
答案 0 :(得分:5)
将自动管理连接。但是,有一些(或至少可以像评论所示)与DataContext相关的额外资源。在垃圾收集器销毁DataContext之前,不会释放这些资源。因此,通常最好确保在不再需要DataContext时调用dispose。
using (ProjDataContext db = new ProjDataContext()) {
bool hasPassword = (from p in db.tblSpecUser
where p.UserID == userId
select p.HasPassword).FirstOrDefault();
return hasPassword;
}
确保在使用块退出时调用db.Dispose()
,从而明确关闭连接。
编辑:在讨论之后,我自己查看了DataContext配置(也使用了Reflector),并找到了从DataContext.Dispose
调用的以下代码(FW 3.5):
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this.provider != null)
{
this.provider.Dispose();
this.provider = null;
}
this.services = null;
this.tables = null;
this.loadOptions = null;
}
}
所以 资源被释放:
DbConnection
,日志(TextWriter
)和DbTransaction
的提供商。CommonDataServices
。LoadOptions
。提供商可能拥有需要处理的资源(DbConnection
和DbTransaction
)。此外,可能必须处理日志的TextWriter
,具体取决于用户分配给TextWriter
的日志记录机制的DataContext
的实例,例如{{1}}。然后自动关闭的FileWriter。
其他属性保持,据我所知 - 没有太多详细信息 - 只有内存,但这也可以通过dispose方法进行垃圾收集,但是,实际内存并不确定获得自由。
所以,最后我完全同意casparOne的声明:
通常,共享像这样的数据访问资源是一个坏主意。
您应该创建资源来访问数据库,执行操作,然后在完成后处理它们。
答案 1 :(得分:2)
从实现的角度来看,不,你没有什么可担心的。但是,这不是由于查询,而是由于DataContext本身的管理。
DataContext类实现了IDisposable接口,因此您应该在完成DataContext实现时调用Dispose。
不幸的是,这也是非常糟糕的做法。您应始终针对合同进行编码,而不是实现。因为DataContext实现了IDisposable,你应该关闭它,即使你知道它什么都不做,因为在将来的实现中绝对会发生变化。
此外,如果您切换到另一个LINQ提供程序,例如LINQ-to-Entities,那么必须在完成后调用Dispose,因为ObjectContext实例中的数据库连接的生命周期(它也实现了IDisposable)非常不同,对Dispose的调用会对这些数据库连接产生影响。
所有这一切,你都有更大的关注。如果您正在共享一个DataContext,则存在跟踪太多对象的风险。除非您将ObjectTrackingEnabled property设置为false,否则DataContext将跟踪通过它选择的每个对象。如果您在应用程序的生命周期内没有进行任何更新操作(或者即使您没有),那么专用于共享DataContext上的对象跟踪的资源数量可能会变得相当大。
开发用于其他数据库技术的规则(例如classes in the System.Data.SqlClient namespace)仍然适用。
通常,共享像这样的数据访问资源是一个坏主意。
您应该创建资源来访问数据库,执行操作,然后在完成后处理它们。
答案 2 :(得分:1)
使用Linq-To-SQL,您通常不需要担心专门打开和关闭作为上下文对象一部分的连接(在您的示例中为db)。关于您必须专门执行此操作的唯一时间是您是通过上下文对象发送直接SQL调用,而不是使用Linq。
使用L2S,您通常希望创建上下文对象,执行工作单元,然后尽快处理对象。您的代码示例对我来说很好。
答案 3 :(得分:0)
我认为使用using语句是一种很好的做法。但我认为您的查询没有任何不妥。
public static bool HasPassword(string userId)
{
using(var db = new ProjDataContext())
{
bool hasPassword = (from p in db.tblSpecUser
where p.UserID == userId
select p.HasPassword).FirstOrDefault();
return hasPassword;
}
}
答案 4 :(得分:0)
数据库连接将在db对象不再存在(已处置)或显式关闭后立即关闭。 在你的样本中,它会(迟早)收集垃圾。