2

制御できない MS SQL テーブルがあり、書き込む必要があります。このテーブルには、自動的にインクリメントされない int 主キーがあります。私はストアド プロシージャを使用できません。他の処理が非常に簡単になるので、Linq to SQL を使用したいと考えています。

私の現在の解決策は、最後の値を読み取ってインクリメントし、それを使用してみてください。衝突が発生した場合は、再度インクリメントして再試行します。

これらの行に沿ったもの:

var newEntity = new Log()
{
    ID = dc.Logs.Max(l => l.ID) + 1,
    Note = "Test"       
};

dc.Logs.InsertOnSubmit(newEntity);

const int maxRetries = 10;
int retries = 0;

bool success = false;
while (!success && retries < maxRetries)
{               
    try
    {                                                           
        dc.SubmitChanges();
        success = true;
    }
    catch (SqlException)
    {
        retries++;
        newEntity.ID = dc.Logs.Max(l => l.ID);                  
    }
}           
if (retries >= maxRetries)
{
    throw new Exception("Bummer...");
}

誰かがより良い解決策を持っていますか?

編集: Jonのおかげで、最大 ID の計算を簡素化しました。私はまだ SQL 思考モードでした。

4

4 に答える 4

2

これは、最大 ID を取得するための高価な方法のように見えます。すでに試しましたか

var maxId = dc.Logs.Max(s => s.ID);

? なんらかの理由でうまくいかないかもしれませんが、本当にうまくいくことを願っています...

(確かに、SQL Server がこれを適切に最適化することは可能です。)

それ以外は、私には問題ないように見えます (臭いですが、必然的にそうです) - しかし、私はこの問題の専門家ではありません...

于 2008-12-22T08:56:02.233 に答える
0

idフィールドを自動インクリメントし、サーバーにID生成を処理させます。

そうしないと、liggett78が言った問題に遭遇します。このスレッドの最大IDの読み取りと送信の間に、別のスレッドが同じIDを読み取ることを妨げるものはありません。

于 2010-01-02T11:39:54.923 に答える
0

以下のように、 TransactionScopeクラスを使用して、操作全体をトランザクションに入れることができます。

using  (TransactionScope scope = new TransactionScope()){
   var maxId = dc.Logs.Max(s => s.ID); 
   var newEntity = new Log(){        
       ID = maxId,        
       Note = "Test"           
   };
   dc.Logs.InsertOnSubmit(newEntity);
   dc.SubmitChanges();
   scope.Complete();
}  

最大IDの取得と新しいレコードの挿入の両方を同じトランザクション内に配置することにより、自分のやり方で再試行することなく挿入を実行できるはずです。

この方法で直面する可能性のある問題の1つは、特にテーブルが頻繁に使用される場合のトランザクションのデッドロックです。追加のエラー処理が必要かどうかを確認するためにテストしてください。

PSコードに最大IDを取得するために、Jon Skeetのコードを含めました。これは、正しく機能すると確信しているためです。:)

于 2008-12-22T09:23:14.613 に答える
0

あなたのアプリがテーブルに挿入する唯一のものであるかどうかを示しませんでした。そうであれば、アプリ/ウェブアプリの開始直後に一度最大値を取得し、次の ID が必要になるたびに Interlocked.Increment を使用します (または、競合状態を除外できる場合は単純な追加)。

于 2008-12-22T09:19:13.467 に答える