1

次のコードの Save メソッドは、「Row not found or changed」というエラーで失敗しています。

Question question = questionService.getQuestionById(id); 
// returning Context.Question.Where(q => q.id == id).SingleOrDefault()

question.Text = "some text";

questionService.Save(question); 
// Context.SubmitChanges();

質問は、CodeSmith および PLINQO テンプレートを使用して生成された DTO です。ただし、「Row not found or changed」エラーは、OnPropertyChanged イベントにカスタム オーバーライドを実装して、レコードが作成または変更されたときに自動的に挿入された後にのみ発生します。生成されたクエリをプロファイリングしました。getQuestionById メソッドが実行されると、通常の select ステートメントが実行されます。ただし、変更日が '2012-07-28 12:15:00.900' として返される場合、レコードを保存しようとすると、Modified = '2012-07-28 12:15: が追加されているため、更新は失敗します。これは、データベースに存在するものとは数ミリ秒異なります。したがって、これは、生成された Question オブジェクトに追加された次のコードと関係があることがわかっています。

protected override void OnPropertyChanged(string property)
{
    this.UpdateProperties(property);
    base.OnPropertyChanged(property);
}

public static void UpdateProperties(this object updatedObject, string property)
{
    if (property == created || property = modified) return;
    // prevents an infinite loop 

    Update(updateObject);
    // sets updatedObject.Created and updateObject.Modified fields
}

秒よりも高い精度を使用するフィールドの場合、dbml で UpdateMode を never に設定することを提案する投稿をいくつか見つけました。これは最後の手段として使用できますが、同じコードを同じデータ型の他のテーブルにしばらくの間問題なく追加してきました。なぜこの 1 つのテーブルでのみ発生しているのかを理解したいと思います。これもランダムに失敗するようです。再現するための具体的な手順はありませんが、デバッグしていないときはより頻繁に発生するようです。

4

1 に答える 1

0

私の推測では、データベースの Modified (および/または Created) 列を使用して同時実行性をチェックしていると思います。このコラムも自分で更新しています。この組み合わせは正しくありません。

より良い方法は、同時実行チェック列としてタイムスタンプを使用することです。この列は SQL サーバーによって設定され (これを使用していると仮定します)、日時ではなく、内部で一意のデータベースによって生成された値です。

いくつかのグーグルは、タイムスタンプ列を設定する方法の基本をよく説明すると思うこの記事をくれました。

于 2012-07-30T06:00:21.773 に答える