C# 我的数据库连接关闭了吗?(Linq到Sql)

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

我正在使用LINQtoSQL,并在一篇博客文章中读到关于尽快关闭数据库连接的内容。例如,他们显示了一个变量正在转换为列表(使用.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;
 }
这个问题可以吗?或者,数据库连接的打开时间是否会超过需要的时间


感谢您提供有关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。所以我不会说它什么都没用。谢谢你的帖子。我发布的代码