首页 > 解决方案 > 使用实体框架插入一到一或零时缺少 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具有PersonIdnull

[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

标签: entity-frameworkentity-framework-6

解决方案


你不想要双重映射,而且你的键有点乱。汽车需要一个人,所以 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。


推荐阅读