我正在尝试了解如何更新一条记录并首次向该记录添加相关实体,然后使用新创建的相关记录中的外键更新原始记录。
例如,假设我有两个表:一个用于人(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,
}
我需要将Lebron James更新为Lebron Brown并添加他的地址。现在我搜索记录并执行以下操作,它会更新Person记录并创建一个地址记录:
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();
问题是当我尝试在保存更改之前使person addressID等于新创建的addressID时,它会给出关于外键约束的错误。
person.AddressID = person.tbl_Address.Id;
db.SaveChanges();
任何帮助将不胜感激。谢谢
链接到CROSSPOST
我最终交叉到EntityFramework Core Github因为我开始认为它可能是一个bug,因为它没有像它应该的那样自动生成子实体中的外键。 GitHub上的问题附加了示例项目(比此处显示的示例稍微复杂一些),如果您想要查看它,则会复制错误:https://github.com/aspnet/EntityFramework/issues/5833
答案 0 :(得分:0)
如果您的模型设置正确,则无需设置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会为您处理。
答案 1 :(得分: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
有值。