异常尝试保存更改时“X”的值未知

Bam*_*dad 16 sql-server entity-framework-core ef-core-5.0

有这两个实体:

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public CompanyVehicle CompanyVehicle { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

public class CompanyVehicle
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Employee Employee { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用Entity Framework Core 5.0.8on SQL Server 2019,CompanyVehicle 的配置为:

entityBuilder.HasOne(t => t.Employee)
    .WithOne(t => t.CompanyVehicle)
    .HasForeignKey<Employee>(t => t.Id)
    .IsRequired();
Run Code Online (Sandbox Code Playgroud)

我们将尝试插入一些东西:

public void Create(Employee employee)
{
    employee.CompanyVehicle = new CompanyVehicle();
    dbContext.Add<Employee>(employee);
    dbContext.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

上面的代码曾经在EF6. Employee 和 CompanyVehicle 表中的两条新记录都是使用相同的Id. 迁移到 后EF Core 5.0.8,dbContext.SaveChanges() 抛出异常:

System.InvalidOperationException:“尝试保存更改时,‘Employee.Id’的值未知。这是因为该属性也是外键的一部分,而关系中的主要实体是未知的。

请注意,这些实体只是示例,在我的例子中不应更改数据库设计。

更新
经过更多调查,我发现我的问题是:
X(主要)和Y(依赖)作为两个表,其中X.IdPK forXY.Idis PK forY以及 FK to ,在 EF Core 中无法插入X记录。X

Bam*_*dad 7

所以我终于找到了问题所在,配置一个Property既是又PKFK可以的,而且非常简单。在从程序集中迁移到EFCorefrom后,我们有了旧代码。EF6该项目是一个框架,因此我们在基础中OnModelCreating使用它来注册来宾项目中的配置。项目将自动查找应用程序路径中项目引用的所有程序集或 DLL 中的所有配置。 关键点是:在显式流畅配置中,与. 所以在for中我们曾经这样写:modelBuilder.ApplyConfigurationsFromAssemblyDbContext
EF CoreFKEF6EF6Employee

this.HasRequired(t => t.CompanyVehicle)
    .WithRequiredDependent(t => t.Employee)
    .HasForeignKey(d => d.Id);
Run Code Online (Sandbox Code Playgroud)

我们EF Core应该写:

b.HasOne(t => t.CompanyVehicle)
   .WithOne(t => t.Employee)
   .HasForeignKey<Employee>(t => t.Id).IsRequired();
Run Code Online (Sandbox Code Playgroud)

第一部分中使用的参数d类型为CompanyVehicle。所以我们的迁移器将旧代码转换为:

b.HasOne(t => t.CompanyVehicle)
   .WithOne(t => t.Employee)
   .HasForeignKey<CompanyVehicle>(t => t.Id).IsRequired();
Run Code Online (Sandbox Code Playgroud)

这是不正确的。通用参数应该是依赖的表类型。我们后来在新的命名空间中修复了该问题,但该ApplyConfigurationsFromAssembly方法在我们的配置后也继续应用过时的代码。
我在末尾使用了以下代码块OnModelCreating来调查该问题:

foreach (var entity in modelBuilder.Model.GetEntityTypes()) 
    foreach(var key in entity.GetForeignKeys())
    {
        //Check what is in the key...
    }
Run Code Online (Sandbox Code Playgroud)

并注意到为我的实体配置了重复的键。