【问题标题】:In a .NET Remoting server application should my database connection object be static在 .NET Remoting 服务器应用程序中,我的数据库连接对象是否应该是静态的
【发布时间】:2023-03-05 08:27:02
【问题描述】:

我有一个使用 .NET Remoting 的客户端服务器应用程序。
我的应用程序 DBQuery 的服务器部分有一个帮助程序类。
DBQuery 持有 DatabaseConnection 和 SQLCommand 对象 Commander 并执行传递给它的查询。

每次执行查询时,都会验证 Commander 是否有打开的连接。
(如有必要,它会重新创建指挥官。)

考虑到它只连接到一个数据库,我应该将我的 DBConnection 设为静态吗? (DBConnection 创建指挥官,DBConnection.CreateCommand()

当前属性定义如下:

/// <summary> connection used for querying with </summary>
public DBConn DBConnection 
{ get { return _conn ?? (_conn = new DBConn()); } }

/// <summary> Command object for processing the queries </summary>
private SqlCommand Commander
{
    get
    { 
      return _commander ??  
            (_commander = DBConnection.Connection.CreateCommand());
    }
}

DBConn - 包装 SqlConnection 并从 app.config 提供适当的连接信息

【问题讨论】:

    标签: .net database remoting .net-remoting


    【解决方案1】:

    即使它是静态的,从不使用单个连接 - 一方面我不相信连接是线程安全的,所以它不一定需要请从两个不同的客户端同时调用。

    即使我错了(如果我错了,我仍然不会在多个线程之间共享一个连接),但如果数据库服务器发生问题,假设它重新启动或服务本身确实(由于您的支持团队发布了升级),那么连接将被断开并且您无法再次重新打开它 - 您的服务/应用程序必须重新启动。很有可能它实际上会在您下次尝试对其执行某些操作时抛出异常。

    另外,你在哪里处理连接?处理静态对象非常困难,除非您完成工作以挂钩关闭事件,这并不总是可靠的。依靠 AppDomain 的关闭来为您处理东西并不是一个好的做法。

    在需要时创建连接,并在完成后将其丢弃。根据您提供的代码,简单来说:

    using(var conn = new DbConn().Connection)
    {
      SqlCommand command = conn.CreateCommand();
      /* query and get results here */
    }
    

    虽然实际上你可能想让你 DbConnIDisposable 并链接到底层 ConnectionDispose 方法在它的 IDisposable.Dispose 的实现中 - 你可以这样做

    using(var dbconn = new DbConn())
    {
      //now you can use dbconn.Connection knowing that it will be disposed of
    }
    

    注意 - 如果 new DbConn() 被工厂方法或属性 get 替换,using 块仍然有效 - 它只是确保在块退出时在对象上调用 Dispose(),即使出现异常发生。

    通过这样做,您可以解决我在答案前半部分强调的所有问题。

    【讨论】:

    • 但这不会导致每个查询都使用它自己的连接吗?我宁愿将 DB 连接本身与生命 DBQuery 联系起来(这样我就可以为多个查询重复使用 1 个连接。)但是有没有一种“干净”的方法可以绕过将 DBQuery 的所有用法包装在 using 中阻止?
    • 仅当您以这种方式编写代码时 - 没有什么可以阻止您为多个查询重用相同的连接。至于需要绕过using,你为什么要这样做?这不是约定俗成的问题,而是正确使用对象的问题。查看 Linq to SQl、实体框架和其他 ORM - 它们几乎都需要使用 using 模式,因为它是与数据库对话的正确方式。正确的处理不仅仅是一件好事——服务器本身需要知道你已经完成了它,以便它可以为其他数据库上的其他客户端提供服务
    • 为了清楚起见,命令对象也实现了 IDisposable。
    【解决方案2】:

    基础架构在幕后进行连接管理(包括池化),因此我的建议是不要将代码设为静态,以保持代码更简洁。

    【讨论】:

      猜你喜欢
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 2020-02-24
      • 1970-01-01
      • 2011-01-06
      相关资源
      最近更新 更多