C# 理解实体框架';这是多对多的关系。为什么我的代码在尝试添加更多数据时会崩溃?

C# 理解实体框架';这是多对多的关系。为什么我的代码在尝试添加更多数据时会崩溃?,c#,asp.net-core,many-to-many,entity-framework-core,C#,Asp.net Core,Many To Many,Entity Framework Core,我正在尝试创建一个联接表,该表结合了Employee表和Tractor表,以记录员工每次分配/取消分配卡车的情况。我可以记录最初的employeeID和truckId,但一旦我尝试在不同的时间和日期记录employeeID和truckId的第二个,代码就会崩溃。因此,Datetime对象始终是唯一的 这是它显示的错误: SqlException:违反主键约束“PK_DriverTractorsAssignmentHistory”。无法在对象“dbo.drivertractorssignmentH

我正在尝试创建一个联接表,该表结合了Employee表和Tractor表,以记录员工每次分配/取消分配卡车的情况。我可以记录最初的employeeID和truckId,但一旦我尝试在不同的时间和日期记录employeeID和truckId的第二个,代码就会崩溃。因此,Datetime对象始终是唯一的

这是它显示的错误:

SqlException:违反主键约束“PK_DriverTractorsAssignmentHistory”。无法在对象“dbo.drivertractorssignmentHistory”中插入重复的密钥。重复的键值为(1,2)。 声明已终止

使用多对多关系是我能想到的一种解决方案,它可以在每次为员工分配卡车时捕获数据。如果你有更好的解决方案,请告诉我

 public class Employee
 { 
    public int EmployeeID { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }

    public int? TractorID { get; set; }
    public virtual Tractor Tractor { get; set; }
    public virtual List<DriverTractorAssignmentHistory>DriverTractorAssignmentHistories { get; set; }
 }

public class Tractor
{
    public int TractorID { get; set; }
    public string TruckNumber {get; set;}
    public string Status { get; set; } 
    public virtual Employee Employee { get; set; }
    public virtual List<DriverTractorAssignmentHistory> DriverTractorAssignmentHistories { get; set; }

    public Tractor()
    {
        Status = "Available";
    }
}


public class TrailerOrderDbContext:DbContext
{
    public DbSet<Employee> Employees { get; set; } 
    public DbSet<DriverTractorAssignmentHistory> DriverTractorsAssignmentHistory { get; set; }
    public DbSet<Tractor> Tractors { get; set; }

    public TrailerOrderDbContext(DbContextOptions<TrailerOrderDbContext> options)
        : base(options)
    {
    }  

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<DriverTractorAssignmentHistory>().HasKey(co => new { co.EmployeeId, co.TractorId });

        modelBuilder.Entity<DriverTractorAssignmentHistory>()
        .HasOne(e => e.Driver)
        .WithMany(c => c.DriverTractorAssignmentHistories)
        .HasForeignKey(trac => trac.TractorId);

        modelBuilder.Entity<DriverTractorAssignmentHistory>()
        .HasOne(trac => trac.Tractor)
        .WithMany(c => c.DriverTractorAssignmentHistories)
        .HasForeignKey(e => e.EmployeeId);
 }

 }
公共类员工
{ 
public int EmployeeID{get;set;}
公共字符串名{get;set;}
公共字符串MiddleName{get;set;}
公共字符串LastName{get;set;}
公共int?TractorID{get;set;}
公共虚拟拖拉机{get;set;}
公共虚拟ListDriverTractorAssignmentHistories{get;set;}
}
公营拖拉机
{
公共int TractorID{get;set;}
公共字符串TruckNumber{get;set;}
公共字符串状态{get;set;}
公共虚拟员工{get;set;}
公共虚拟列表驱动器ractorassignmenthistories{get;set;}
公共拖拉机()
{
Status=“可用”;
}
}
公共类TrailerOrderDbContext:DbContext
{
公共数据库集雇员{get;set;}
公共数据库集驱动器TractorsAssignmentHistory{get;set;}
公共数据库集{get;set;}
公共TrailerOrderDbContext(DbContextOptions选项)
:基本(选项)
{
}  
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasKey(co=>new{co.EmployeeId,co.TractorId});
modelBuilder.Entity()
.HasOne(e=>e.Driver)
.WithMany(c=>c.DriverTractorAssignmentHistory)
.HasForeignKey(trac=>trac.TractorId);
modelBuilder.Entity()
.HasOne(trac=>trac.Tractor)
.WithMany(c=>c.DriverTractorAssignmentHistory)
.HasForeignKey(e=>e.EmployeeId);
}
}

onmodellcreating(ModelBuilder-ModelBuilder)
中删除这一行代码,因为这一行代码可以防止重复数据输入,并防止多对多映射:

    modelBuilder.Entity<DriverTractorAssignmentHistory>()
        .HasKey(co => new { co.EmployeeId, co.TractorId });

虽然这解决了错误,但我认为这不是一个好答案。OP应该定义一个唯一键,这意味着它还应该包含添加该键的日期时间。要创建唯一键,您可以参考此链接
https://stackoverflow.com/questions/18889218/unique-key-constraints-for-multiple-columns-in-entity-framework
。但是在这种情况下,
唯一键
应该是多个列的组合。我的建议是将
EmployeeId
和TractorId`作为唯一键。EmployeeId和TractorId在
DriverTractorAssignmentHistory
中必须是唯一的,因为它们是键的一部分,但它们不够唯一,因为OP每天可以多次分配/取消分配拖拉机的员工,所以它将失败。他需要的是另一个领域,使其独一无二。So`.HasKey(co=>new{co.EmployeeId,co.TractorId,co.AssignTimestamp}@谢谢。根据您的建议修改了我的答案。在DriverTractorAssignmentHistory上创建一个DateTime字段,并使其成为键的一部分,因此插入时这三个字段的组合应该是唯一的。您能否向我们展示
DriverTractorAssignmentHistory
类的代码?
    modelBuilder.Entity<DriverTractorAssignmentHistory>()
      .HasKey(co => new { co.EmployeeId, co.TractorId, co.AssignTimestamp };