entity-framework - 使用实体框架插入一到一或零时缺少 ID
问题描述
针对 SQL 服务器使用 EF6,当保存具有一对零或一关系的记录时,需要如何配置映射以便在“零或-”中设置“一”的 id一”
一个简单的例子是:
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public virtual Car Car { get; set; }
}
public class Car
{
public int CarId { get; set; }
public string Make { get; set; }
public int? PersonId { get; set; }
public virtual Person Person { get; set; }
}
使用映射配置
public class PersonMap : EntityTypeConfiguration<Person>
{
public PersonMap()
{
HasKey(x => x.PersonId);
HasOptional(x => x.Car)
.WithRequired(x => x.Person);
}
}
public class CarMap : EntityTypeConfiguration<Car>
{
public CarMap()
{
HasKey(x => x.CarId);
Property(x => x.Make).IsRequired();
HasRequired(x => x.Person)
.WithOptional(x => x.Car);
}
}
针对上述映射的任何变体运行非常简单的测试总是会导致实体Car
具有PersonId
null
[TestFixture]
public class PersonMappingTest
{
[Test]
public void ItWorks()
{
var person = new Person {Name = "Test person"};
var car = new Car {Person = person, Make = "Ford"};
person.Car = car;
car.Person = person;
using (var cx = new CompWalkContext())
{
cx.Persons.Add(person);
cx.SaveChanges();
}
}
}
-
CarId Make PersonId
----- ---- --------
1 Ford NULL
2 Ford NULL
这是可能的,还是Person
在添加之前需要保存实体Car
?
解决方案
你不想要双重映射,而且你的键有点乱。汽车需要一个人,所以 PersonID 不能为空,因为一个人可能有车,也可能没有车。如果您想要 Car 上的 PersonId,则它是人和汽车之间的 1-0..1。从这里您可以在 Car WithOptional 上设置 HasRequired,但您需要告诉 EF 要使用的密钥。在数据库中,Car 表上的 PersonID 必须不可为空。
public class Person
{
public int PersonId { get; set; }
public string Name { get; set; }
public virtual Car Car { get; set; }
}
public class Car
{
public int CarId { get; set; }
public string Make { get; set; }
public virtual Person Person { get; set; }
}
public class PersonMap : EntityTypeConfiguration<Person>
{
public PersonMap()
{
HasKey(x => x.PersonId);
}
}
public class CarMap : EntityTypeConfiguration<Car>
{
public CarMap()
{
HasKey(x => x.CarId);
Property(x => x.Make).IsRequired();
HasRequired(x => x.Person)
.WithOptional(x => x.Car)
.Map(x => x.MapKey("PersonId")); // Tell EF to use the PersonId on the Car to resolve the Person reference.
}
}
然后当你去创造一个人和车...
var person = new Person { /* set properties */ };
dbContext.Persons.Add(person);
// Or retrieve your Person from the DbSet..
var car = new Car
{
/* set properties... */
Person = person // associate the person to the car.
};
dbContext.Cars.Add(car);
dbContext.SaveChanges();
现在,如果您取回汽车,您可以访问他们的 .Person。如果您检索到有车的人,您可以访问他们的 .Car。
推荐阅读
- excel - 搜索以连接列并在从另一个工作簿中选择额外数量之间,该数量应增加
- javascript - react-native-webrtc 远程流在 android 5.0.2 上不起作用
- sql - 如何提取SAS PROC SQL passthru中的记录,按日期过滤,但日期是字符串格式?
- javascript - 如何为每个 wordpress 帖子点击创建单独的弹出表单
- reactjs - 设置标题React的行数
- linux - 如何通过 ssh 将 VSC 与 Fedora 连接?
- docker - 更新 docker 上的根证书
- typescript - 汇总:从外部模块捆绑/嵌入 wasm 代码
- javascript - 由于大量 JSON 响应,AJAX 请求失败
- c++ - 从静态变量的析构函数调用 Windows 7 上的 std::conditional_variable notify() 问题