7

この投稿の例としてNorthwindデータベースを使用していますが、エンティティフレームワークを使用してデタッチされたエンティティをデータベースに保存する際に問題が発生しています。

領土と地域を取得するには、次の2つの方法があります。

    static List<Region> GetRegions()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Region.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Region.ToList();
        }
    }

    static List<Territories> GetTerritories()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Territories.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Territories.ToList();
        }
    }

これらのメソッドはどちらも正常に機能し、切り離された状態で必要なオブジェクトのコレクションを取得します。

SaveEntityという静的メソッドもあります。これは、古いエンティティと現在編集されているエンティティの両方を取り込みます。これは次のとおりです。

    static void SaveEntity(EntityObject oldEntity, EntityObject newEntity)
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Attach(oldEntity);
            entities.ApplyPropertyChanges(newEntity.EntityKey.EntitySetName, newEntity);
            entities.SaveChanges();
        }
    }

このメソッドは、オブジェクトへの変更がデータベースに保存される場合に部分的に機能しますが、関連するオブジェクトの関係への変更は保存されません。

私の例として、上記のメソッドを呼び出す次のコードがあります。

            List<Territories> territories = GetTerritories();
        List<Region> regions = GetRegions();

        Region region = regions.Where(n => n.RegionID == 2).FirstOrDefault();
        Territories oldTerritory = territories.Where(n => n.TerritoryID == "01581").FirstOrDefault();
        Territories newTerritory = ObjectCopier.Clone<Territories>(oldTerritory);

        newTerritory.TerritoryDescription = "Hello World";
        newTerritory.Region = region;

        SaveEntity(oldTerritory, newTerritory);

TerritoryDe​​scriptionへの変更は正常に保存されますが、Regionへの変更は保存されません。データベースでは、RegionID=2ではなくRegionID=1のままになります。

ApplyPropertyChangesが関連オブジェクトへの変更を伝播しない理由について誰かが私に洞察を提供できますか?

また、私がこの問題を回避する方法を知っている人はいますか?

4

2 に答える 2

2

リージョンとテリトリーを別々にフェッチする代わりに、同じクエリで両方をフェッチします。次のようなものです(エンティティを更新したいのですが、新しいエンティティを作成したくないと思います)。

static List<Region> GetTerritoriesWithRegions()
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Territories.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            return entities.Territories.Include("Region").ToList();
        }
    }

次に、それらを次のように更新します。

   List<Territories> territoriesWithRegions = GetTerritoriesWithRegions();
        Territories territory = territories.Where(n => n.TerritoryID == "01581").FirstOrDefault();
        territory.TerritoryDescription = "Hello World";
        Region region = territories.Where(p => p.Any(q => q.Region.RegionID == 2)).FirstOrDefault().Region;
        territory.Region = region;

        SaveEntity(territory);

そしてそれらを保存します。

static void SaveEntity(EntityObject entity)
    {
        using (NorthwindEntities entities = new NorthwindEntities())
        {
            entities.Attach(entity);
            entities.Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);            
            entities.SaveChanges();
        }
    }

私はこれをメモ帳にコーディングしたので、間違いがあるかもしれません。あればコメントしてください。それに応じて更新します。

于 2012-04-20T08:59:56.827 に答える
1

ここで答えを見つけることができると思います (Alex James の方が優れています)。 関連エンティティによるエンティティ フレームワークの更新

基本的に、その理由は、EF 関係もオブジェクトであり、エンティティ (削除、追加など) のようなステータスを持っているため、コンテキストにも元の参照値が必要になるためです。

于 2009-11-08T20:46:09.950 に答える