3

正確なエンティティを投稿しています:

    public class Person : ContactableEntity
{

    public Plan Plan { get; set; }

    public int Record { get; set; }

    public int PersonTypeValue { get; set; }

}

次のコードを使用して、切断されたコンテキストの方法で更新しています。

        public void Update(DbSet MySet, object Obj)
    {
        MySet.Attach(Obj);
        var Entry = this.Entry(Obj);
        Entry.State = EntityState.Modified;
        this.SaveChanges();
    }

これは、私の dbContext によって公開されたメソッドであり、次のように呼び出されます。

PersistentManager.Update(PersistentManager.Personas,UpdatedPersona);

問題は、EF が参照されている Plan オブジェクト以外のすべてのプロパティを更新することです。誰かが間違いを教えてもらえますか? 事前 : エンティティは、すべてのプロパティが正しく設定された状態で更新ポイントに到達します。EF はデータベース内の FK の更新に失敗するだけです (例外はありません) 更新: このような問題を解決しようとしましたが、うまくいきませんでした:

            PersistentMgr.Contacts.Attach(Obj);
            PersistentMgr.Entry(Obj).State = EntityState.Modified;
            PersistentMgr.Entry(Obj.Plan).State = EntityState.Modified;
            PersistentMgr.SaveChanges();
4

1 に答える 1

6

あなたが必要...

this.Entry(person).State = EntityState.Modified;
this.Entry(person.Plan).State = EntityState.Modified;

... の状態を設定するpersonModified、 person は state のコンテキストにアタッチされますModifiedが、関連するエンティティは stateperson.PlanにアタッチされるためですUnchanged

Personエンティティが切り離されている間にとの間の関係Planが変更された場合 (特にモデルのように、外部キーがプロパティとして公開されていない場合 (「独立した関連付け」))、エンティティを正しく更新することはより困難になります。基本的には、データベースから元のオブジェクト グラフを読み込み、関係が変更されている場合は切り離されたグラフと比較し、読み込まれたグラフに変更をマージする必要があります。ここに例があります(その回答の 2 番目のコード スニペットを参照してください)。

編集

動作することを示す例 (EF 5.0 を使用):

using System.Data;
using System.Data.Entity;
using System.Linq;

namespace EFModifyTest
{
    public class Person
    {
        public int Id { get; set; }
        public Plan Plan { get; set; }
        public int Record { get; set; }
        public int PersonTypeValue { get; set; }
    }

    public class Plan
    {
        public int Id { get; set; }
        public string SomeText { get; set; }
    }

    public class MyContext : DbContext
    {
        public DbSet<Person> Contacts { get; set; }
        public DbSet<Plan> Plans { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());

            // Create a person with plan
            using (var ctx = new MyContext())
            {
                ctx.Database.Initialize(true);

                var plan = new Plan { SomeText = "Old Text" };
                var person = new Person { Plan = plan, Record = 1, PersonTypeValue = 11 };

                ctx.Contacts.Add(person);

                ctx.SaveChanges();
            }
            // see screenshot 1 from SQL Server Management Studio

            Person detachedPerson = null;
            // Load the person with plan
            using (var ctx = new MyContext())
            {
                detachedPerson = ctx.Contacts.Include(c => c.Plan).First();
            }

            // Modify person and plan while they are detached
            detachedPerson.Record = 2;
            detachedPerson.PersonTypeValue = 12;
            detachedPerson.Plan.SomeText = "New Text";

            // Attach person and plan to new context and set their states to Modified
            using (var ctx = new MyContext())
            {
                ctx.Entry(detachedPerson).State = EntityState.Modified;
                ctx.Entry(detachedPerson.Plan).State = EntityState.Modified;

                ctx.SaveChanges();
            }
            // see screenshot 2 from SQL Server Management Studio
        }
    }
}

SQL Server Management Studio のスクリーンショット 1 (変更前、Person表が左、Plan表が右):

変更前

SQL Server Management Studio のスクリーンショット 2 (変更後、Person表が左、Plan表が右):

修正後

うまくいかない場合は、テスト モデルとコードに重要な違いがあるはずです。どれかわかりません。詳細を提供する必要があります。

編集 2

関係Personを別の (既存の) に変更する場合Planは、元の関係をロードしてから関係を更新する必要があります。ObjectContext独立した関連付け (モデルに FK プロパティなし) を使用すると、変更追跡を使用してのみ関係を更新できます (変更トラッカーでの関係エントリのより高度な変更は別として)。

var originalPerson = this.Contacts.Include(c => c.Plan)
    .Single(c => c.Id == person.Id);
this.Plans.Attach(person.Plan);

this.Entry(originalPerson).CurrentValues.SetValues(person);
originalPerson.Plan = person.Plan;

this.SaveChanges();
于 2012-11-14T23:36:27.070 に答える