0

適切な場所にあるにもかかわらず、データ テーブルで同期データ アクセスを実現できませんTransactionScope

SQL データベースに格納されているシリアル化されたオブジェクト グラフへのアクセスを担当する WCF サービスがあります。これは、 と呼ばれる操作コントラクトによって達成されましたGetObject。ここでは、指定された を使用してテーブルからシリアル化されたオブジェクトを返しますtokenId。tokenId は、どの時点でも 2 人のユーザーが同じ行 (オブジェクト グラフ) にアクセスできないようにするために、このシナリオに関連しています。

そして、wcf サービスに関して言えば、私たちのサービスはマルチスレッド ( CuncurrencyisMultipleInstanceContextModeis PerCall) です。

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)a を呼び出します。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();
    }
  }

質問 これらすべてを配置すると、ほとんどの場合、複数のユーザーが同じオブジェクト グラフにアクセスすることになります。

4

1 に答える 1

0

ここで何を達成しようとしているのかわかりません。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に設定して Service を作成する方が簡単ではありませんSingleか?

于 2013-11-11T11:06:27.247 に答える