EF Code First Detached Entity不更新对象引用

时间:2012-11-13 17:14:22

标签: entity-framework ef-code-first stateless

我发布了确切的实体:

    public class Person : ContactableEntity
{

    public Plan Plan { get; set; }

    public int Record { get; set; }

    public int PersonTypeValue { get; set; }

}

我正在使用以下代码以disconected context方式更新:

        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();

1 个答案:

答案 0 :(得分:5)

你需要......

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

...因为当您将person的状态设置为Modified时,此人会附加到状态Modified中的上下文,但会附加person.Plan等相关实体在州Unchanged

如果在实体分离时更改了PersonPlan之间的关系,则更加困难(特别是在您的模型中,当没有外键作为属性公开时(“独立关联”) “))正确更新实体。您基本上需要从数据库加载原始对象图,如果关系已更改,则将其与分离图进行比较,并将更改合并到加载的图中。一个示例是here(请参阅该答案中的第二个代码段)。

修改

显示它有效的示例(使用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表是对的):

Before modification

来自SQL Server Management Studio的屏幕截图2(修改后,Person表保留,Plan表格正确):

After modification

如果它不起作用,我的测试模型和代码必须有重要的区别。我不知道哪一个,你必须提供更多细节。

修改2

如果您将关系从Person更改为另一个(现有)Plan,则必须加载原始关系,然后更新关系。使用独立关联(模型中没有FK属性),您只能通过使用更改跟踪来更新关系(除了ObjectContext更改跟踪器中关系条目的更高级修改):

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();