私はその前にメソッドを作成しました:
- テーブルをロックしました
- そこから値を読み取る
- 更新された値を書き戻しました
- テーブルのロックを解除しました
コードは Oracle で機能しました。現在、SQL Server 2008 では機能しません。方法は以下のとおりで、ロック解除コマンドを実行するとSqlException
、テキストが表示されます。
「NOLOC」は、認識されたテーブル ヒント オプションではありません。テーブル値関数または CHANGETABLE 関数のパラメーターとして意図されている場合は、データベース互換モードが 90 に設定されていることを確認してください。
コード:
public static int GetAndSetMaxIdTable(DbProviderFactory factory, DbConnection cnctn, DbTransaction txn, int tableId, string userName, int numberOfIds)
{
bool isLocked = false;
string sql = string.Empty;
string maxIdTableName;
if (tableId == 0)
maxIdTableName = "IdMax";
else
maxIdTableName = "IdMaxTable";
try
{
bool noPrevRow = false;
int realMaxId;
if (factory is OracleClientFactory)
sql = string.Format("lock table {0} in exclusive mode", maxIdTableName);
else if (factory is SqlClientFactory)
sql = string.Format("select * from {0} with (TABLOCKX)", maxIdTableName);
else
throw new Exception(string.Format("Unsupported DbProviderFactory -type: {0}", factory.GetType().ToString()));
using (DbCommand lockCmd = cnctn.CreateCommand())
{
lockCmd.CommandText = sql;
lockCmd.Transaction = txn;
lockCmd.ExecuteNonQuery();
isLocked = true;
}
using (DbCommand getCmd = cnctn.CreateCommand())
{
getCmd.CommandText = CreateSelectCommand(factory, tableId, userName, getCmd, txn);
object o = getCmd.ExecuteScalar();
if (o == null)
{
noPrevRow = true;
realMaxId = 0;
}
else
{
realMaxId = Convert.ToInt32(o);
}
}
using (DbCommand setCmd = cnctn.CreateCommand())
{
if (noPrevRow)
setCmd.CommandText = CreateInsertCommand(factory, tableId, userName, numberOfIds, realMaxId, setCmd, txn);
else
setCmd.CommandText = CreateUpdateCommand(factory, tableId, userName, numberOfIds, realMaxId, setCmd, txn);
setCmd.ExecuteNonQuery();
}
if (factory is OracleClientFactory)
sql = string.Format("lock table {0} in share mode", maxIdTableName);
else if (factory is SqlClientFactory)
sql = string.Format("select * from {0} with (NOLOC)", maxIdTableName);
using (DbCommand lockCmd = cnctn.CreateCommand())
{
lockCmd.CommandText = sql;
lockCmd.Transaction = txn;
lockCmd.ExecuteNonQuery();
isLocked = false;
}
return realMaxId;
}
catch (Exception e)
{
...
}
}
それで、ここで何がうまくいかないのですか?このエラーはどこから来たのですか? サーバーまたはクライアント? Cコードからステートメントをコピーしましたが、そこで動作するはずです。残念ながら、デバッグして機能するかどうかを確認することはできません。
編集:(読み取りまたは更新せずに)ロックおよびロック解除しようとすると、同じ例外が発生します。
ありがとう & BR -マティ