CTP5更新级联

时间:2011-02-18 08:17:42

标签: c# entity-framework entity-framework-ctp5

我需要CTP5的添加或更新模式。 假设模型:

public class User
{
    public int UserId { get; set; }
    public ICollection<Address> Addresses { get; set; }
}
public class Address
{
    public int AddressID { get; set; }
    public string Location { get; set; }
}

如果我添加新用户,则还会填充相应的地址表。 但是如果用户已经在DB中,我将得到一个DbUpdateException。在这种情况下,我希望使用新数据更新数据库中的数据。我怎么能这样做?

数据库中的数据

表格地址

地址ID位置

1 JohnPlace

2 MaryPlace

3 JimmyPlace

我更新的用户在Addresses集合1中有AddressId:2,Location = GeorgePlace。 但是对于ID = 2,在Db中已经存在location = MarryPlace的记录。我希望GeorgePlace覆盖MarryPlace。

我不能拥有未分配给用户的地址

我创建了一个像这样的用户:

var user=new User();
user.Id=GetUserIDfromService();
foreach(var address in GetAddressesFromService(user.Id)){
    user.Addresses.Add(address);
}
context.Users.Add(user);
context.SaveChanges();//this may throw an exception, because there is already a user with this id.

2 个答案:

答案 0 :(得分:0)

如果您想更新现有用户,请不要插入(请勿拨打Add()) 首先按用户ID加载用户,然后修改其属性,并在上下文中调用SaveChanges()

var db = new DatabaseContext();
var user = db.Users.Find(myUserId);
user.Name = "New Name";
db.SaveChanges();

答案 1 :(得分:0)

您当前的问题是您准备新的User对象并填充其地址,但地址不是通过相同的上下文从DB加载的,因此上下文不知道它们。当您调用Add方法时,它将获取对象图中的所有对象并将它们标记为新(要插入)。避免这种情况的唯一方法是手动说出哪个地址是新的,哪个只是在将它们添加到用户实例之前从上下文修改或加载地址。

标记地址的代码如下所示:

var user = new User(); 
user.Id = GetUserIDfromService(); 
context.Users.Add(user); 
foreach(var address in GetAddressesFromService(user.Id))
{
  context.Addresses.Attach(address);
  // Let say that new address always have 0 Id      
  context.Entry(address).State = address.Id == 0 ? EntityState.Added : EntityState.Modified;      
  user.Addresses.Add(address); 
} 

context.SaveChanges();