質問

最初にエンティティフレームワークコードを使用し、WCF REST HTTPインターフェイスを介してNorthWindデータベースを公開しています。

注文を作成してから、別のサービスを通じて必要な各注文を別々に追加することは意味がないため、OrderDetailsテーブル(注文アイテム)を公開していません。私の考えでは、それは成功または失敗する原子トランザクションである必要があります。したがって、クライアントに渡すときにOrder.OrderDetailsコレクションを含め、注文が作成または更新されたときにそれを取得すると仮定します。

ただし、問題は、更新のために注文エンティティを再接続する際に、OrderDetailsコレクションの変更を検出することです。注文自体は、それらのプロパティを更新するように変更されたまま設定できますが、これは注文アイテムにカスケードされません。そのため、手動で更新されたものを変更して変更することができますが、問題はそもそも更新されたものを把握することにあります。新しいOrderDetailを変更すると、保存しようとするとエラーが発生します。

新しいコレクションアイテムのIDを0に設定するよう勧告を読み、サーバーでそれを使用して、それが新品か既存かを決定します。ただし、Northwindは、OrderDetailsにOrderIDとProductIDの間に複合キーを使用しています。これらは両方ともクライアントが設定する必要があるため、新しいものを検出する方法が見つかりません。さらに、削除されたOrderDetailは分離したグラフには存在せず、削除されたものを把握し、明示的に削除する必要があります。

どんなアドバイスでも大歓迎です。

public override Order Update(Order entity)
{
    dbset.Attach(entity);
    DataContext.Entry(entity).State = EntityState.Modified;

    foreach (var orderDetail in entity.OrderDetails)
    {
        DataContext.Entry(orderDetail).State = EntityState.Modified;
    }

    return entity;
}
役に立ちましたか?

解決

これは 一般的で複雑な問題 そして、あなたのためにそれをする魔法はありません。私のソリューション(およびすべてのシナリオで機能する唯一のソリューション)は、 Order 再び更新方法で、変更を手動でマージします。

public override Order Update(Order entity)
{
    // No attach of entity

    var attached = DataContext.Orders.Include(o => o.OrderDetails).SingleOrDefault(...);
    if (attached == null) ...

    // Merge changes from entity to attached - if you change any property
    // it will be marked as modified automatically

    foreach (var detail in attached.OrderDetails.ToList())
    {
        // ToList is necessary because you will remove details from the collection

        // if detail exists in entity check if it must be updated and set its state

        // if detail doesn't exists in entity remove if from collection - if it is \
        // aggregation (detail cannot exists without Order) you must also delete it 
        // from context to ensure it will be deleted from the database
    }

    foreach (var detail in entity.OrderDetails)
    {
        // if it doesn't exists in attached create new detail instance,
        // fill it from detail in entity and add it to attached entity - 
        //you must not use the same instance you got from the entity
    }

    DataContext.SaveChanges();

    return entity;
}

また、タイムスタンプを使用している場合は、手動でチェックする必要があります。

代替シナリオは、削除された詳細には新しい詳細とネガティブIDに使用される0で説明したものですが、クライアントで行う必要があるロジックです。また、場合によっては機能します。

他のヒント

私は最近、しばらく前に雇用主のために行ったいくつかの仕事をオープンすることを許可されました(もちろんいくつかの変更があります)。私は実際にこの問題を解決するための拡張法を書きました、あなたはそれをで得ることができます http://refactorthis.wordpress.com/2012/12/11/introducing-graphdiff-for-entity-frame--frame-frame-code-firowing-automated-praph-of-a-graph-of-detached-entities/

それが役に立てば幸い!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top