1

DB に投稿を追加するときに問題が発生しました。この「追加」関数は複数のスレッドから呼び出されます。そして、通常は非常に迅速に、これが重要かどうかはわかりませんが、それが機能する方法です.

コード:

private object dbLock = new object();

public void Add(string fileName, DateTime collectionTime)
    {
        try
        {
            lock (dbLock)
            {
                var collection = new Collection
                {
                    Filename = fileName,
                    Datetime = collectionTime,
                };
                _entities.AddToCollection(collection);
                _entities.SaveChanges();
                CollectionChanged(collection, null);
            }
        }
        catch (Exception ex)
        {
        }
        finally
        {

        }
    }

私の問題は、SaveChanges が呼び出されると、次の例外が発生することです。

データベースへの変更は正常にコミットされましたが、オブジェクト コンテキストの更新中にエラーが発生しました。ObjectContext が矛盾した状態にある可能性があります。内部例外メッセージ: オブジェクトのキー値が ObjectStateManager 内の別のオブジェクトと競合するため、AcceptChanges を続行できません。AcceptChanges を呼び出す前に、キー値が一意であることを確認してください。

私が見つけたすべての答えは、あなたが追加しなければならないことと関係がありますStoreGeneratedPattern="Identity"。私はすでにこれを行いましたが、役に立ちません

<Property Name="ID" Type="integer" Nullable="false" StoreGeneratedPattern="Identity" />

これを解決する他の方法はありますか?

4

1 に答える 1

3

結局のところ、スレッド間でオブジェクト コンテキストを共有することは、本当に悪い考えです。オブジェクト コンテキストは、作業単位として使用することを目的としています。典型的な使用法:

using(var ctx = new SomeObjectContextType()) // assuming IDisposable
{
    // not shown: get some records, if needed
    ...
    // not shown: update, add, remove some records, if needed

    ctx.SaveChanges();
} // and now it is gone, never to be used again

一部のシナリオでは、それよりも少し複雑になる可能性があります。たとえば、ページ/リクエストの期間中オブジェクト コンテキストを保持するなどです。ただし、呼び出し元間で共有することはできません。これには多くの理由がありますが、基本的にすべての競合する更新をロックする必要があります。ここでの「更新」には、データベースから任意のレコードを読み取る、またはプロパティを遅延ロードするという単純な行為が含まれます。オブジェクト コンテキストが複数のスレッドからアクセスされたときに気まぐれになることは驚くべきことではありません。そのシナリオは (通常) サポートされていません。

さらに、長寿命のオブジェクト コンテキストを持つことには、他にも問題があります。

  • 時折、事態が悪化します (たとえば、タイムアウト、デッドロック、ロールバック、または単純な接続エラーなど)。Dispose()ここで対応する適切な方法は、現在壊れているオブジェクト コンテキスト (適切な場合はそれ)を単に破棄し、それを忘れることです。変更を再適用する場合は、新しいオブジェクト コンテキストから開始します。
  • オブジェクト コンテキストには、アイデンティティ マップと変更管理システムが含まれます。1回の操作よりも長く保持すると、オブジェクトが徐々に蓄積されます。これにより、メモリの問題が発生するだけでなく、パフォーマンスが徐々に低下します。読み取り/更新操作ごとに、トロールするデータ量が増え続けるためです。

基本的に、ここでの「修正」は次のとおりです。それをしないでください。これは、オブジェクト コンテキストの正しい使用法ではありません。アプリケーション全体の共有オブジェクト コンテキストを持たない。

于 2013-06-18T08:39:42.813 に答える