19

を使用して変更を行うと、別のユーザーがその行の一部のデータを変更したときに、競合のある行または競合している変更のあるフィールドのいずれかを示すことなくSubmitChanges()、LINQ がChangeConflictExceptionエラー メッセージの例外で終了することがあります。Row not found or changed

どの行に競合があり、どのフィールドで競合が発生しているかを判断する方法はありますか? また、LINQ に問題を無視させ、単にデータをコミットさせる方法はありますか?

さらに、この例外が行のデータが変更された場合に発生するの、それとも LINQ が変更しようとしているフィールドのデータが変更された場合にのみ発生するのかを知っている人はいますか?

4

7 に答える 7

24

競合がどこにあるかを確認する方法は次のとおりです (これは MSDN の例であるため、大幅にカスタマイズする必要があります)。

try
{
    db.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException e)
{
    Console.WriteLine("Optimistic concurrency error.");
    Console.WriteLine(e.Message);
    Console.ReadLine();
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
        Customer entityInConflict = (Customer)occ.Object;
        Console.WriteLine("Table name: {0}", metatable.TableName);
        Console.Write("Customer ID: ");
        Console.WriteLine(entityInConflict.CustomerID);
        foreach (MemberChangeConflict mcc in occ.MemberConflicts)
        {
            object currVal = mcc.CurrentValue;
            object origVal = mcc.OriginalValue;
            object databaseVal = mcc.DatabaseValue;
            MemberInfo mi = mcc.Member;
            Console.WriteLine("Member: {0}", mi.Name);
            Console.WriteLine("current value: {0}", currVal);
            Console.WriteLine("original value: {0}", origVal);
            Console.WriteLine("database value: {0}", databaseVal);
        }
    }
}

問題を無視してコミットするには、次のようにします。

db.SubmitChanges(ConflictMode.ContinueOnConflict);
于 2008-08-28T16:16:19.787 に答える
19

これら (部分クラスでデータコンテキストに追加できるものは、これがどのように機能するかを理解するのに役立つ場合があります。

public void SubmitKeepChanges()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            //Keep current values that have changed, 
//updates other values with database values

            occ.Resolve(RefreshMode.KeepChanges);
        }
    }
}

public void SubmitOverwrite()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            // All database values overwrite current values with 
//values from database

            occ.Resolve(RefreshMode.OverwriteCurrentValues);
        }
    }
}

public void SubmitKeepCurrent()
{
    try
    {
        this.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
        foreach (ObjectChangeConflict occ in this.ChangeConflicts)
        {
            //Swap the original values with the values retrieved from the database. No current value is modified
            occ.Resolve(RefreshMode.KeepCurrentValues);
        }
    }
}
于 2008-08-28T16:17:33.683 に答える
4

エラー メッセージの内容とはまったく関係のない状況で、このエラーが発生しました。

私がしたことは、1 つの DataContext を介して LINQ オブジェクトをロードし、別の DataContext を介してそのオブジェクトに対して SubmitChanges() を試みたところ、まったく同じエラーが発生しました。

私がしなければならなかったのは、DataContext.Table.Attach(myOldObject) を呼び出してから、SubmitChanges() を呼び出すことでした。

特に、競合があってはならないという意見がある場合は、一見の価値があります。

于 2008-08-28T16:15:58.383 に答える
2

O/R デザイナーの列または型が SQL データベースの列と一致しない場合、特に 1 つの列が SQL で NULL 可能であるが O/ Rデザイナー。

O/R-Designer のテーブル マッピングが SQL データベースと一致するかどうかを確認してください。

于 2008-09-17T15:02:37.223 に答える
2

@vzczc に感謝します。あなたが提供した例は非常に役に立ちましたが、解決後に SubmitChanges を再度呼び出す必要があることがわかりました。これが私の変更された方法です-誰かの役に立てば幸いです。

    /// <summary>
    /// Submits changes and, if there are any conflicts, the database changes are auto-merged for 
    /// members that client has not modified (client wins, but database changes are preserved if possible)
    /// </summary>
    public void SubmitKeepChanges()
    {
        this.Submit(RefreshMode.KeepChanges);
    }

    /// <summary>
    /// Submits changes and, if there are any conflicts, simply overwrites what is in the database (client wins).
    /// </summary>
    public void SubmitOverwriteDatabase()
    {
        this.Submit(RefreshMode.KeepCurrentValues);
    }

    /// <summary>
    /// Submits changes and, if there are any conflicts, all database values overwrite
    /// current values (client loses).
    /// </summary>
    public void SubmitUseDatabase()
    {
        this.Submit(RefreshMode.OverwriteCurrentValues);
    }

    /// <summary>
    /// Submits the changes using the specified refresh mode.
    /// </summary>
    /// <param name="refreshMode">The refresh mode.</param>
    private void Submit(RefreshMode refreshMode)
    {
        bool moreToSubmit = true;
        do
        {
            try
            {
                this.SubmitChanges(ConflictMode.ContinueOnConflict);
                moreToSubmit = false;
            }
            catch (ChangeConflictException)
            {
                foreach (ObjectChangeConflict occ in this.ChangeConflicts)
                {
                    occ.Resolve(refreshMode);
                }
            }
        }
        while (moreToSubmit);

    }
于 2012-09-19T01:00:30.840 に答える
-1

「また、LINQ に問題を無視させ、単にデータをコミットさせる方法はありますか?」

エンティティの 'Update Check' プロパティを 'Never' に設定して、そのフィールドがオプティミスティック コンカレンシー チェックに使用されないようにすることができます。

以下も使用できます。

db.SubmitChanges(ConflictMode.ContinueOnConflict)
于 2008-08-28T21:51:12.383 に答える