【问题标题】:Fail to enable synchronized access though transaction is in place尽管事务已到位,但无法启用同步访问
【发布时间】:2013-11-11 10:52:59
【问题描述】:

即使我有TransactionScope,我也无法实现对数据表的同步数据访问。

我有一个WCF服务,负责访问存储在SQL数据库中的序列化对象图;这是通过一个名为GetObject 的操作合约实现的,它使用给定的tokenId 从表中返回一个序列化对象。 tokenId 在我们的场景中是相关的,以确保在任何时间点都没有两个用户可以访问同一行(对象图)。

说到 wcf 服务,我们的服务是多线程的(CuncurrencyMultipleInstanceContextModePerCall)。

public CustomObject GetObject(string username, string userTeam)
{
     int tokenID = Database.GetNextToken(username, userTeam);

     MainDataLayer.LoadData loadData = new MainDataLayer.LoadData();
     return loadData.GetObject (tokenID);
}

GetNextToken(tokenID) 调用CLR stored procedure 以访问事务范围内的数据库表。

 public static void usp_GetNextToken(SqlString userID, SqlString userTeam)
  {
    using (TransactionScope transactionScope = new TransactionScope())
    {
      using (SqlConnection connection = new SqlConnection("context connection = true"))
      {
        connection.Open();

        SqlDataRecord record = new SqlDataRecord(new SqlMetaData[1]
        {
          new SqlMetaData("objectId", SqlDbType.Int)
        });

SqlDataAdapter sqlDataAdapter2 = new SqlDataAdapter(new SqlCommand("SELECT top (1) * FROM myTable where lockedby= ' ' ORDER BY createdate DESC ", connection));


          DataSet dataSet2 = new DataSet();
          if (connection.State == ConnectionState.Closed)
            connection.Open();
          ((DataAdapter) sqlDataAdapter2).Fill(dataSet2);

          if (dataSet2.Tables[0].Rows.Count > 0)
          {
            new SqlCommand(string.Concat(new object[4]
            {
              (object) "UPDATE myTable SET lockedby = '",
              (object) userID.ToString(),
              (object) "' WHERE objectId = ",
              (object) int.Parse(dataSet2.Tables[0].Rows[0][" objectId "].ToString())
            }), connection).ExecuteNonQuery();
            record.SetSqlInt32(0, (SqlInt32) int.Parse(dataSet2.Tables[0].Rows[0][" objectId "].ToString()));
            SqlContext.Pipe.Send(record);
            return;
          }
        }
        record.SetSqlInt32(0, (SqlInt32) 0);
        SqlContext.Pipe.Send(record);
      }
      transactionScope.Complete();
    }
  }

问题 有了所有这些,我们在大多数情况下最终都会让多个用户访问同一个对象图。

【问题讨论】:

    标签: c# sql multithreading wcf


    【解决方案1】:

    不确定您要在这里实现什么。 TransactionScope 仅在适当的位置,以便您可以提交或回滚 SQL 语句。

    我认为您可以使用lock 来防止处理多个请求:

    private static object DatabaseLock = new object();
    
    public CustomObject GetObject(string username, string userTeam)
    {
        lock (DatabaseLock)
        {
            int tokenID = Database.GetNextToken(username, userTeam);
    
            MainDataLayer.LoadData loadData = new MainDataLayer.LoadData();
            return loadData.GetObject (tokenID);
        }
    }
    

    但这会影响性能。

    创建一个将Concurrency设置为Single的Service是不是更简单?

    【讨论】:

    猜你喜欢
    • 2023-01-11
    • 2019-12-25
    • 2013-08-25
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 2017-08-02
    相关资源
    最近更新 更多