【问题标题】:Should I put lock statements around C# Database Calls?我应该在 C# 数据库调用周围放置锁定语句吗?
【发布时间】:2012-01-30 11:52:05
【问题描述】:

我正在创建一个类,用作在 SQL Server 数据库中读取、插入和更新值的门户。该类实现了单例设计模式,因此任何时候都只会有一个该类的实例。

此类对数据库值的每个操作(读取、写入和删除)都有单独的方法,每个方法都将打开一个 SQLConnection,创建、填充和执行 SQLCommand,最后在完成后关闭连接。

这是添加值的示例:

public void AddGlossaryValue(string name, string value)
{
   SqlConnection connection = null;
   SqlCommand command = null;

   try
   {
      connection = new SqlConnection(connectionString);
      connection.Open();

      command = new SqlCommand(SQL_INSERT_COMMAND, connection);
      command.Parameters.Add("@name", SqlDbType.NVarChar, 50);
      command.Parameters.Add("@value", SqlDbType.NVarChar, 50);

      command.Parameters["@name"].Value = name;
      command.Parameters["@value"].Value = value;

      command.ExecuteNonQuery();
   }
   catch (Exception ex)
   {
      // handle exception - omitted in this example because it's irrelevant
   }
   finally
   {
      try
      {
         connection.Close();
      }
      catch (Exception) { }
   }
}

我来自 Java 背景,通常您会将此类方法声明为 Synchronized,这意味着该方法在任何时候都只能从一个源执行。从我对 C# 的研究来看,实现这一点的典型方法似乎是锁定和对象。

但是,我的问题是,在上述情况下是否建议这样做,如果是,锁定对象应该放在哪里?是否会在创建 SQLConnection 之前立即进行?

非常感谢

【问题讨论】:

  • 忠告:您可以将数据库连接放在using 块中,而不是try/finally。
  • 感谢您的建议,会做的

标签: c# locking


【解决方案1】:

为什么要锁定?您没有在 dll 代码中使用任何共享资源。

只需捕获您可能会从碰撞中看到的 sql 错误。如果你插入已经存在的东西,那么你可以做任何当时合适的事情。

在代码中保存共享资源的锁定;多个线程可能正在访问您需要确保决定性行为的地方。这段代码看起来就像你只是在向数据库发射一些东西,你不会得到任何你无法通过在这里不使用锁来轻松解释的行为。

【讨论】:

  • +1 表示不太常见的常识。很多人只是扔锁(或在java中标记同步的方法),甚至没有丝毫线索。只是“线程安全”的模糊概念。
【解决方案2】:

我完全不喜欢为此目的使用 Singleton。使用单个实例将为线程安全带来重大飞跃。不需要锁。

【讨论】:

  • 在这种情况下需要一个单例,因为它缓存了键/值对列表。目的是防止应用程序所需的数据库读取次数。因此,如果有 10 个人在使用相应的 ASP.Net 页面,他们都将共享同一个键/值对资源池。
  • 更不用说可测试性了,因为你不能模拟一个静态类。
  • @DBM:我可以毫不费力地嘲笑他们。
【解决方案3】:

那段代码不需要锁,因为您没有访问任何共享状态。但是您关于“缓存键/值对列表”的评论肯定需要围绕读取/写入列表。

【讨论】:

  • 关于读/写列表的要点。我忽略了这一点。
【解决方案4】:

虽然我可以想象在少数情况下这会非常有用(例如,您正在使用 SQLite),但在大多数情况下,自己进行锁定是个坏主意。

【讨论】:

    【解决方案5】:

    您可以明确使用lock(){//code block} 语句,它会确保线程执行不会进入临界状态。

    但是,据我所知,如果您对每个命令使用不同的 SqlConnections,那么它会自动成为线程安全的。

    另外,您可以使用 SqlTransaction 类。

    SqlCommand command = connection.CreateCommand();
        SqlTransaction transaction;       
        transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);       
        command.Connection = connection;
        command.Transaction = transaction;
    

    只是为了对您的应用程序有额外的控制权。

    【讨论】:

      猜你喜欢
      • 2011-01-10
      • 1970-01-01
      • 2020-09-15
      • 2012-01-12
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多