5

多層ビジネスアプリケーションにはObservableCollections、サービスコールから返される自己追跡エンティティがあります。

アイデアは、エンティティを取得し、それらをコレクションクライアント側に追加、更新、および削除してから、これらの変更をサーバー側に送信して、データベースに永続化できるようにすることです。

自己追跡エンティティは、その名前が示すように、自分の状態を追跡します。新しいSTEが作成されると、追加状態になります。プロパティを変更すると、変更状態が設定されます。削除状態にすることもできますが、エンティティがObservableCollection(明らかに)から削除されると、この状態は設定されません。この動作が必要な場合は、自分でコーディングする必要があります。

私の現在の実装では、エンティティがから削除されたObservableCollectionときに、それをシャドウコレクションに保持します。これObservableCollectionにより、がサーバーに返送されたときに、削除されたアイテムを一緒に送信できるため、EntityFrameworkはそれらを削除することを認識します。

次のようなもの:

protected IDictionary<int, IList> DeletedCollections = new Dictionary<int, IList>();

protected void SubscribeDeletionHandler<TEntity>(ObservableCollection<TEntity> collection)
{
    var deletedEntities = new List<TEntity>();
    DeletedCollections[collection.GetHashCode()] = deletedEntities;

    collection.CollectionChanged += (o, a) =>
        {
            if (a.OldItems != null)
            {
                deletedEntities.AddRange(a.OldItems.Cast<TEntity>());
            }
        };
}

これで、ユーザーが変更をサーバーに保存することにした場合、削除されたアイテムのリストを取得して、それらを一緒に送信できます。

ObservableCollection<Customer> customers = MyServiceProxy.GetCustomers();

customers.RemoveAt(0);

MyServiceProxy.UpdateCustomers(customers);

この時点で、UpdateCustomersメソッドはアイテムが削除されたかどうかをシャドウコレクションで確認し、それらをサーバー側に送信します。

これらのシャドウコレクションのライフサイクルについて考え始めるまで、このアプローチは問題なく機能します。基本的に、ObservableCollectionガベージコレクションの場合、辞書からシャドウコレクションを削除する必要があることを知る方法はありません。

この場合、基本的に手動のメモリ管理を行う複雑なソリューションを思いつきました。私はを維持し、WeakReferenceObservableCollection秒ごとに参照が非アクティブであるかどうかを確認します。その場合、シャドウコレクションを削除します。

しかし、これはひどい解決策のようです...StackOverflowの集合的な天才がより良い解決策に光を当てることができることを願っています。

編集:

結局、私はサブクラス化することにしましたObservableCollection。サービスプロキシコードが生成されるため、派生型を返すように変更するのは比較的簡単な作業でした。

すべての助けをありがとう!

4

3 に答える 3

1

独自の「弱参照 + ポーリング Is it Dead, Is it Alive」ロジックを展開する代わりに、HttpRuntime.Cache(Web プロジェクトだけでなく、すべてのプロジェクト タイプから利用可能) を使用できます。

寛大なタイムアウト、または元のコレクションがまだ生きているかどうかを確認できるデリゲート (またはその両方) を使用して、各シャドウ コレクションをキャッシュに追加します。

独自のソリューションと大きく異なるわけではありませんが、試行済みで信頼できる .Net コンポーネントを使用しています。

それ以外に、ObservableCollection を拡張し、代わりにその新しいクラスを使用すること (これは小さな変更ではないと思います)、またはUpdateCustomersメソッドを変更/ラッピングしてシャドウ コレクション フォームを削除することを検討しています。DeletedCollections

申し訳ありませんが、他に何も思いつきませんが、これが役立つことを願っています。
帯域幅

于 2010-06-03T16:29:43.803 に答える
1

ObservableCollection を置き換える可能性がある場合 (たとえば、すべてのコレクション インスタンスに共通のファクトリを使用している場合)、ObservableCollection をサブクラス化し、このコレクションに属する削除済みアイテムをクリーンアップする Finalize メソッドを追加できます。

もう 1 つの方法は、削除されるアイテムの計算方法を変更することです。元のコレクションを維持し、クライアントに浅いコピーを提供できます。コレクションが戻ってきたら、2 つを比較して、もはや存在しないアイテムを確認できます。コレクションがソートされている場合、比較はコレクションのサイズに対して線形時間で実行できます。並べ替えられていない場合、変更されたコレクションの値をハッシュ テーブルに入れ、それを使用して元のコレクションの各値を検索できます。エンティティに自然な ID がある場合、それをキーとして使用すると、返されたコレクションに存在しない、つまり削除されたアイテムを安全に判断できます。これも線形時間で実行されます。

それ以外の場合、元のソリューションはそれほど悪くはありません。Java では、WeakReference は、参照がクリアされたときに呼び出されるコールバックを登録できます。.NET には同様の機能はありませんが、ポーリングを使用するのが近似値です。私はこのアプローチがそれほど悪いとは思わない。

余談ですが、GetHashCode() が異なるコレクションに対して同じ値を返すことを心配していませんか? コレクションへの弱い参照を使用する方がキーとして適切な場合があり、衝突の可能性はありません。

于 2010-06-04T04:43:30.453 に答える
1

あなたは良い道を進んでいると思います。この状況ではリファクタリングを検討します。私の経験では、99% のケースで、ガベージ コレクターがメモリ管理を素晴らしいものにします。実際の作業はほとんど必要ありません。

しかし、1% のケースでは、その領域のキャッシング/メモリ管理を強化することで、条件を上げて「古い学校」に行かなければならないことに誰かが気付く必要があります。あなたがそのような状況にあることに気づき、IDispose/WeakReference のトリックを回避しようとしていることに脱帽です。あなたのコードで働く次の人を本当に助けてくれると思います。

解決策については、状況をよく把握していると思います

-オブジェクトを作成する必要がある時期を明確にする -オブジェクトを破棄する必要がある時期を明確にする -オブジェクトをサーバーにプッシュする必要がある時期を明確にする

幸運を!それがどうなるか教えてください:)

于 2010-06-08T04:19:05.463 に答える