9

アイテムにバインドされた Grid がList<T>あります。ユーザーが「更新」を押すたびに、データベースから変更が取得され、バインドされたリストが更新されます。グリッドにアイテムが重複して追加されるという問題が発生しましたが、その理由がわかりません。

List<int>データベース呼び出しは、変更されたレコード ID と、変更さList<MyClass>れたレコードの更新されたデータの2 つの値を返します。更新する必要があるものを見つけるためにデバッグしている既存のコード コードは、次のようになります。

public void FindUpdates(IList<MyClass> existingRecords,
                    IList<MyClass> updatedRecords,
                    List<int> updatedIds,
                    out IDictionary<int, int> existing,
                    out IDictionary<int, int> updated,
                    out List<int> updates,
                    out List<int> removes,
                    out List<int> adds)
{
    updates = new List<int>();
    removes = new List<int>();
    adds = new List<int>();

    existing = FindUpdated(existingRecords, updatedIds);
    updated = FindUpdated(updatedRecords, updatedIds);

    if (updatedIds != null)
    {
        // split add/update and remove
        foreach (int id in updatedIds)
        {
            if (!existing.ContainsKey(id))
                adds.Add(id);
            else if (updated.ContainsKey(id))
                updates.Add(id);
            else
                removes.Add(id);
        }

        WriteToLog(updatedIds, adds, updates, removes);
    }
}

private IDictionary<int, int> FindUpdated(IList<MyClass> records, List<int> updatedIds)
{
    IDictionary<int, int> foundItems = new Dictionary<int, int>();

    if (records != null && updatedIds != null)
    {
        for (int i = 0; i < records.Count; i++)
        {
            IMyClass r = records[i] as IMyClass ;
            if (r != null && !r.IsDisposed)
            {
                if (updatedIds.Contains(r.Id))
                {
                    foundItems.Add(r.Id, i);
                }
            }
        }
    }

    return foundItems;
}

呼び出しの結果、FindUpdates()既存Dictionary<Id, Data>のレコードの 、Dictionary<Id, Data>それらを置き換える更新されたレコードの 、およびList<int>データ ソースからアイテムを追加、削除、または更新する必要がある ID の を取得します。

場合によっては、レコードがグリッドに 2 回追加されることがありますが、このコードのどこが間違っているのか、一生わからないことがあります。

これらのインスタンスの 1 つからログ ファイルを取得したところ、次の一連のイベントを明確に確認できます。

  • データリストにアイテム#2を追加
  • 20分後、アイテム#2が再びデータリストに追加されます

WriteToLog()2番目の追加から、

  • updatedIds値 1、2、および 3 を含む
  • adds1 と 2 を含む
  • updates3個入り

他のログ エントリに基づいて、アイテム #2 が以前に追加され、削除されていないことを明確に確認できexistingRecordsます。さらに、アイテム #2 は最初の追加と 2 番目の追加の間に数回正常に更新されたため、理論上のコードは機能するはずです。UI のスクリーンショットもあり、データのグリッドにアイテム #2 の両方のコピーが表示されています。updatesadds

ノート...

  • IsDisposedアイテムのオーバーライドさ.Dispose()れたメソッドでのみ true に設定されます。こんなことにはならなかったと思います。

    編集:それ以来、ログステートメントを追加しましたが、これが発生したときにIsDisposed設定されていないことを確認できtrueます。

  • これは数人の異なるユーザーに数回発生しているため、一度だけではありません。ただし、オンデマンドで問題を再現することはできません。

  • レコードのグリッドはかなり大きくなり、平均して数千項目になります。

  • DB呼び出しが無効な値を返す、または同じアイテムを持たないリストを返すという考えを排除していませんが、それが結果にどのように影響するかはわかりません

  • このバグの動作を確認できたのは、いくつかのテストを実行していて、他のユーザーがレコード #2 をかなり頻繁に変更していたときです。

  • これはすべてバックグラウンド スレッドで実行されます

  • ログに基づくと、これは一度だけ実行されていました。前は 1 分前に実行され、次は 2 分後に実行されました。

  • ログ ファイルから、項目 2 が正しく更新された後、2 回目の追加が誤って行われたことがわかります。したがって、このコードは数回前に既存のデータ セットで機能していました。

上記のコードに、これを引き起こす可能性のあるものはありますか? それとも、私が気付いていない C# のまれな既知の問題で、これが発生する可能性がありますか?

4

2 に答える 2

1

List<T>上記のコードを使用して既存のアイテムが見つからない理由はありません。

Dictionary<int,int>アイテムの Id と既存のリスト内のアイテムのインデックスを含む値が出力値に含まれていることに気付いたとき、頭の中で警鐘を鳴らす必要がありました。

existingRecords[existing[id]]何が起こっていたかというと、を使用してアイテムが削除されていexisting[id]たということですexistingRecords。これを機能させるには、アイテムを最大のインデックスから削除する必要があります。大きいインデックスよりも小さいインデックスが削除されると、大きいインデックスの位置が 1 つずれ、間違った項目が削除されます。

アイテムが重複していた理由は、2 つのコレクションが維持されていたためです。1 つはアイテムが新規/更新/削除されたかどうかを判断するために使用され、もう 1 つは UI に表示するためにバインドされていました。最初のコレクションは誤って更新されていましたが、2 番目のコレクションは更新されていなかったため、アイテムが UI コレクションに複数回追加される可能性がありました。

私の短期的な解決策は、removesコレクションを並べ替えて、各項目のインデックスで降順に並べ替えられるようにすることでした。私の長期的な解決策は、コードを書き直すことです。:)

于 2014-05-15T14:31:03.727 に答える
0
List.Contains(r) 

a.Equals(r) であるリスト内のオブジェクト a を見つけようとします。MyClass が Equals をオーバーライドしない場合、同じクラスの 2 つの異なるオブジェクトが等しいことを確信できません。これについては完全にはわかりませんが、 equals は GetHashCode() を使用していると思います。一方をオーバーライドする場合は、もう一方をオーバーライドする必要があります。

ここにMSDNがあります: http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx

于 2014-03-05T16:28:56.543 に答える