我发布了确切的实体:
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();
答案 0 :(得分:5)
你需要......
this.Entry(person).State = EntityState.Modified;
this.Entry(person.Plan).State = EntityState.Modified;
...因为当您将person
的状态设置为Modified
时,此人会附加到状态Modified
中的上下文,但会附加person.Plan
等相关实体在州Unchanged
。
如果在实体分离时更改了Person
和Plan
之间的关系,则更加困难(特别是在您的模型中,当没有外键作为属性公开时(“独立关联”) “))正确更新实体。您基本上需要从数据库加载原始对象图,如果关系已更改,则将其与分离图进行比较,并将更改合并到加载的图中。一个示例是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
表是对的):
来自SQL Server Management Studio的屏幕截图2(修改后,Person
表保留,Plan
表格正确):
如果它不起作用,我的测试模型和代码必须有重要的区别。我不知道哪一个,你必须提供更多细节。
修改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();