我的数据库连接是否关闭? (Linq to Sql)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的数据库连接是否关闭? (Linq to Sql)相关的知识,希望对你有一定的参考价值。

我正在使用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;
 }

这个查询好吗?或者数据库连接是否保持打开的时间超过必要的时间?

谢谢你的任何建议

答案

连接将自动管理。但是,有一些(或至少可以像评论所示)与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

提供者可能拥有需要处置的资源(DbConnectionDbTransaction)。此外,可能必须处理日志的TextWriter,这取决于用户分配给TextWriter的日志记录机制的DataContext的实例,例如,然后自动关闭的FileWriter。

其他属性保持,据我所知 - 没有太多细节 - 只有内存,但这也可以通过dispose方法用于垃圾收集,但是,它确定何时内存实际被释放。

所以,最后我完全赞同casparOne的声明:

通常,共享像这样的数据访问资源是个坏主意。

您应该创建资源来访问数据库,执行操作,然后在完成后处置它们。

另一答案

从实施的角度来看,不,你没有什么可担心的。但是,这不是由于查询,而是由于DataContext本身的管理。

DataContext类实现了IDisposable接口,因此您应该在完成DataContext实现后调用Dispose。

现在,这是一个well known fact that calling Dispose on DataContext instances do nothing, and therefore are not technically required

不幸的是,这也是非常糟糕的做法。您应始终对合同进行编码,而不是实施。因为DataContext实现了IDisposable,所以你应该关闭它,即使你知道它什么也不做,因为在将来的实现中它可以绝对改变。

此外,如果你切换到另一个LINQ提供程序,比如LINQ-to-Entities,那么你必须在完成后调用Dispose,因为ObjectContext实例中的数据库连接的生命周期(也实现了IDisposable)是非常不同的,并且调用Dispose对这些数据库连接有影响。

所有这一切,你都有更大的关注。如果您正在共享一个DataContext,则存在跟踪太多对象的风险。除非您将ObjectTrackingEnabled property设置为false,否则DataContext将跟踪通过它选择的每个对象。如果您在应用程序的生命周期内没有执行任何更新操作(或者即使您没有),则专用于共享DataContext上的对象跟踪的资源数量可能会变得相当大。

使用其他数据库技术(例如classes in the System.Data.SqlClient namespace)的规则仍然适用。

通常,共享像这样的数据访问资源是个坏主意。

您应该创建资源来访问数据库,执行操作,然后在完成后处置它们。

另一答案

使用Linq-To-SQL,您通常不需要担心专门打开和关闭作为上下文对象一部分的连接(在您的示例中为db)。关于你必须专门做这件事的唯一时间是你通过上下文对象发送直接SQL调用,而不是使用Linq。

使用L2S,您通常希望创建上下文对象,执行工作单元,然后尽快处理对象。您的代码示例对我来说很好。

另一答案

我认为使用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;
    }
}
另一答案

数据库连接将在db对象不再存在(已处置)或显式关闭后立即关闭。在您的样本中,它将(迟早)收集垃圾。

以上是关于我的数据库连接是否关闭? (Linq to Sql)的主要内容,如果未能解决你的问题,请参考以下文章

SQL to LINQ 工具 [关闭]

LINQ to SQL 左外连接

Linq-to-sql 不产生多个外连接?

Linq to Sql:多个左外连接

是否可以在选择完成之前设置列别名,使用 Linq to SQL

带有存储过程的实体框架 VS LINQ to SQL VS ADO.NET? [关闭]