2016-06-21 125 views
0

我试图了解如何更新一条记录并首次向该记录添加相关实体,然后使用新创建的相关外键更新原始记录记录。添加相关实体后更新实体的外键

例如,假设我有两个表:一个用于人员(tbl_person),另一个用于地址(tbl_address)。

+----+------------+-----------+-----------+ 
| PK | First Name | Last Name | AddressFK | 
+----+------------+-----------+-----------+ 
| 1 | Michael | Jordan |   1 | 
| 2 | Lebron  | James  |   | 
+----+------------+-----------+-----------+ 

    public int PersonID { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int? AddressID { get; set; } 
    public virtual tbl_Address tbl_Address { get; set; } 

    entityBuilder 
     .HasOne(t => t.tbl_Address) 
     .WithOne(t => t.tbl_Person) 
     .HasForeignKey<tbl_Person>(d => d.AddressID) 
     .IsRequired(false); 

+----+-------------------+----------+-------+ 
| PK | Address Line 1 | City | State | 
+----+-------------------+----------+-------+ 
| 1 | 123 Sesame Street | New York | NY | 
+----+-------------------+----------+-------+ 

    public int AddressID { get; set; } 
    public string AddressLine1 { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public virtual tbl_Person tbl_Person { get; set; } 

我的应用程序收到需要更新的后续JSON记录。

{ 
    "address": { 
    "addressLine1": "789 Hollywood Ave", 
    "city": "Hollywood", 
    "state": "CA" 
    }, 
    "firstname": "Lebron", 
    "lastname": "Brown", 
    "id": 2, 
} 

我需要更新勒布朗詹姆斯是勒布朗布朗,也加上他的地址。现在我搜索记录,并执行以下操作,它更新的人员记录,并创建一个地址记录:

var person = _db.tbl_Person 
    .Include(t => t.tbl_address) 
    .Where(t => t.Id == json.id).First(); 

person.firstname = json.firstname; 
person.lastname = json.lastname; 
if(person.tbl_Address == null) 
{ 
    person.tbl_Address = new tbl_Address() { 
     AddressLine1 = json.address.addressLine1, 
     City = json.address.city, 
     State = json.address.state, 
    }; 
} 

db.SaveChanges(); 

问题是,当我试图让对方addressID保存更改之前等于新建addressID它给我一个关于外键约束的错误。

person.AddressID = person.tbl_Address.Id; 
db.SaveChanges(); 

任何帮助,将不胜感激。谢谢

LINK TO CROSSPOST

我结束了crossposting到的EntityFramework核心Github上,因为我开始认为这可能是一个错误,因为它不产生在子实体的外键自动喜欢它应该。 GitHub上的问题附有示例项目(稍微比这里显示的示例更复杂),如果您想要查看它,请复制错误:https://github.com/aspnet/EntityFramework/issues/5833

+0

具有数据注释或EntityTypeConfigurations的类声明将有所帮助,但基本上不会手动更新FK,因为在SaveChanges调用之前,它们都采用默认值(default(int)== 0 '),这就是为什么有一个例外。 –

+0

好吧,这是我的问题更多样本..但它是相当接近我的实际表。我按要求添加了类声明。 – chris

+0

在你的例子中,通过设置'person.tbl_Address',EF将插入地址并自行更新'Person'。 –

回答

0

如果您的模型设置正确, t需要设置AddressID。它会自动更新。在SaveChanges()调用AddressID的值之前的时间是default(int) == 0 - 这就是发生异常的原因。这个声明应该足够了:

public class Person { 
    public int AddressID {get;set;} 
    [ForeignKey(nameof(Person.AddressID))] 
    public Address tbl_Address {get;set;} 
} 

TU更新地址我的代码这种方式改变

if (json.address != null) 
{ 
    if(person.tbl_Address == null) 
    { 
     person.tbl_Address = new tbl_Address(); 
    } 
    person.tbl_Address.AddressLine1 = json.address.addressLine1, 
    person.tbl_Address.City = json.address.city, 
    person.tbl_Address.State = json.address.state 
} 

,如果人已经有一个地址,它会更新,否则会造成新的。不需要设置外键 - EF会为您处理。

+0

我最初认为我没有必要定义addressID,直到我运行它,它创建了预期的地址,但从未将addressID添加到person表中。我的表格略有不同,我只是忽略了业务逻辑以专注于问题,但总体来说它是一样的。我正在做一个快速愚蠢的项目来测试这些示例表,看看我是否得到相同的结果 – chris

+0

我更新了示例以根据需要执行更新/插入。 –

+0

我最终交叉发送到EntityFramework Core Github,因为我开始认为它可能是一个错误,因为它不会自动生成子实体中的外键。在GitHub上的问题有示例项目攻击与错误复制如果你想检查出来:https://github.com/aspnet/EntityFramework/issues/5833 – chris

0

在EF有两种方式设置的关系,

  • 设置FK属性:当实体在你的数据库已经存在使用此变种。

  • 设置导航属性:如果是新实体,则使用此变体。当您拨打SaveChanges时,新实体将保存在您的数据库中,并且FK列也将被设置。

所以,如果Address已经存在,你需要做的唯一的就是搜索其Id,并设置在Person实体的FK财产。

如果Address不存在,然后创建一个新的实例,并调用SaveChanges

person.tbl_Address = new tbl_Address() { 
    AddressLine1 = json.address.addressLine1, 
    City = json.address.city, 
    State = json.address.state, 
}; 
db.SaveChanges(); 

之后叫你应该能够看到AddressId在您Person实体的值。

+0

,但在我的情况下,该人存在且地址不存在,我该怎么办?我需要更新人员的姓氏并导航到该地址并首次添加地址,但也要将该地址ID返回给该人员并更新该表格 – chris

+0

Hi @chris,您是否看到我答案的最后部分? – octavioccl

+0

我最终交叉发送到EntityFramework Core Github,因为我开始认为它可能是一个错误,因为它不会自动生成子实体中的外键。在GitHub上的问题有示例项目攻击与复制的错误,如果你想检查它:https://github.com/aspnet/EntityFramework/issues/5833 – chris