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;

...因为当您将 person 的状态设置为状态时,personModified人会附加到 state 中的上下文,Modified但相关实体(例如person.Planstate )会附加到该上下文中Unchanged

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

编辑

显示它有效的示例(使用 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(修改前,PersonPlan表,右表):

修改前

SQL Server Management Studio的截图2(修改后,PersonPlan表,右表):

修改后

如果它对您不起作用,那么我的测试模型和代码肯定有重要区别。我不知道是哪一个,您必须提供更多详细信息。

编辑 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();
于 2012-11-14T23:36:27.070 回答