C# 我的数据库连接关闭了吗?(Linq到Sql)
我正在使用LINQtoSQL,并在一篇博客文章中读到关于尽快关闭数据库连接的内容。例如,他们显示了一个变量正在转换为列表(使用.ToList()),而不是实际返回Linq查询。我有以下代码:C# 我的数据库连接关闭了吗?(Linq到Sql),c#,database,performance,linq-to-sql,database-connection,C#,Database,Performance,Linq To Sql,Database Connection,我正在使用LINQtoSQL,并在一篇博客文章中读到关于尽快关闭数据库连接的内容。例如,他们显示了一个变量正在转换为列表(使用.ToList()),而不是实际返回Linq查询。我有以下代码: public static bool HasPassword(string userId) { ProjDataContext db = new ProjDataContext(); bool hasPassword = (from p in db.tblSpecUser
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;
}
这个问题可以吗?或者,数据库连接的打开时间是否会超过需要的时间
感谢您提供有关Linq To SQL的任何建议。通常,您不需要特别关心如何打开和关闭作为上下文对象一部分的连接(在您的示例中为db)。只有在通过上下文对象而不是使用Linq发送直接SQL调用的情况下,才需要专门这样做
对于L2S,您通常希望创建上下文对象,完成工作单元,然后尽快处理该对象。您的代码示例在我看来很好。连接将自动管理。然而,与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;
}
在这里,可以确保在using块退出时调用db.Dispose()
,从而显式关闭连接
编辑:讨论结束后,我自己查看了DataContext dispose(也使用Reflector),发现了以下代码(FW 3.5),该代码从DataContext.dispose调用:
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
- 表格词典
加载选项
提供者可能持有需要处置的资源(DbConnection
和DbTransaction
)。此外,根据用户分配给DataContext
的日志记录机制的TextWriter
实例,可能必须处理日志的TextWriter
,例如,随后自动关闭的FileWriter
据我所知,其他属性只保留内存(不需要太多细节),但也可以通过dispose方法进行垃圾收集,但是,它不能确定内存实际释放的时间
最后,我完全同意卡斯帕隆的说法:
一般来说,像这样共享数据访问资源是个坏主意
您应该创建资源来访问数据库,执行操作,然后在完成后处置它们
我认为使用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;
}
}
数据库连接将在数据库对象不再存在(已释放)或显式关闭后立即关闭。
在您的示例中,它(迟早)会被垃圾收集。从实现的角度来看,不,您不必担心任何问题。然而,这并不是由于查询,而是由于数据库本身的管理
DataContext类实现了该接口,因此无论何时使用DataContext实现,都应该调用Dispose
现在,这是一个好消息
不幸的是,这也是非常糟糕的做法。您应该始终根据合同而不是实现来编写代码。因为DataContext实现了IDisposable,所以您应该关闭它,即使您知道它什么都不做,因为这在未来的实现中可能会发生绝对的变化
另外,如果您切换到另一个LINQ提供程序,比如LINQ to Entities,那么您必须在完成后调用Dispose,因为实例(也实现IDisposable)中的数据库连接的生存期非常不同,而调用Dispose会对这些数据库连接产生影响
尽管如此,你还有更大的顾虑。如果共享一个DataContext,则可能会跟踪太多对象。除非将设置为false,否则DataContext将跟踪通过它选择的每个对象。如果您在应用程序的生命周期内没有执行任何更新操作(或者即使您正在执行),那么在共享DataContext上专门用于对象跟踪的资源数量可能会相当大
使用其他数据库技术(例如)开发的规则仍然适用
一般来说,像这样共享数据访问资源是个坏主意
您应该创建资源来访问数据库,执行操作,然后在完成后处理它们。哇,感谢您的快速回复!我将替换所有projdatacontext代码以使用“using”方法,而不是创建新实例并等待调用其Dispose方法。再次感谢您的帮助。值得注意的是,尽管IDisposable是在LINQtoSQL中实现的,但LINQtoSQL的设计者明确表示,在大多数情况下,不需要处理DataContext。请参阅,谢谢您提供的信息。如果我理解正确,这是否意味着尽管在需要更严格地控制GC定时时使用“using”很好,但在使用DataContext(大多数情况下)时实际上并不需要它?@o-logn:这是我的理解。@casperOne:Dispose方法处理提供程序
成员,并设置服务
,表
,以及加载选项
成员为空。SqlProvider
中的Dispose方法(由DataContext Dispose方法调用)关闭连接
成员,并将一组其他成员设置为null。所以我不会说它什么都没用。谢谢你的帖子。我发布的代码