实体框架数据建模:2个外键和一个主键

本文关键字:一个 实体 建模 数据 2个 框架 | 更新日期: 2023-09-27 18:12:15

我有以下表格:

public class Event {
  public int Id {get;set;}
}
public class Participant{
  public int Id {get;set;}
}
public class Registration{
  public int Id {get;set;}
  public int EventId {get;set;}
  public int PaticipantId {get;set;}
}

我将注册Id作为主键,但是如何确保eventid和participant是唯一的呢?我已经考虑过复合键,但是我需要注册上的Id属性,因为我将需要它作为另一个类/表上的外键。

对于任何对我的dbcontext感兴趣的人来说,它是这样的:

modelBuilder.Entity<Registration>()
                .HasRequired(e => e.Participant)
                .WithMany(u => u.Events)
                .HasForeignKey(e => e.ParticipantId);
            modelBuilder.Entity<Registration>()
                .HasRequired(e => e.Event)
                .WithMany(u => u.Participants)
                .HasForeignKey(e => e.EventId);

实体框架数据建模:2个外键和一个主键

创建另一个表,其中包含EventId和PaticipantId作为组合键,然后将该表id放入您的注册表

public class Event {
  public int Id {get;set;}
}
public class Participant{
  public int Id {get;set;}
}
public class NewTable{
   public int Id {get;set;}
   public int EventId  {get;set;}
   public int PaticipantId {get;set;}
}
public class Registration{
  public int Id {get;set;}
  public int NewTableId {get;set;}
}

实际上有许多方法可以确保EventId和PaticipantId的组合是唯一的,无论是否触及您的模型。

它可以在你的数据库中设置:你可以声明两个字段的组合UNIQUE,然后在你的应用程序中捕获错误并按你想要的方式处理它。

还可以在应用程序中直接使用一个函数来验证组合是否存在。(如果存在则返回false)

您还可以在您的模型中添加另一个字段,一个字符串表示相同字段中的两个id,并声明它是唯一的

事实上,有很多方法可以解决你的问题。

您应该在列EventId和ParticipantId的组合上添加一个唯一键

由于您正在使用EF迁移,您可以向您的模型添加唯一的键,并让实体框架在之后为您生成一个新的迁移。然后,此迁移将向数据库添加一个惟一键。根据您的实体框架版本,这将是不同的。

在Entity Framework Core 1.0.0中,这很简单:

modelBuilder.Entity<Registration>().HasIndex(x => new { x.ParticipantId, x.EventId}).IsUnique();

当使用实体框架6时,你可以使用注解或流畅的api(尽管相当冗长):

与注释:

public class Registration
{
  public int Id {get;set;}
  [Index("UQ_Registration_EventId_ParticipantId", 1, IsUnique = true)]
  public int EventId {get;set;}
  [Index("UQ_Registration_EventId_ParticipantId", 2, IsUnique = true)]
  public int PaticipantId {get;set;}
}

或使用流畅的API:

string uniqueIndex = "UQ_Registration_EventId_ParticipantId";
modelBuilder.Entity<Registration>().Property(t => t.EventId)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 1
            }
        )
    );
modelBuilder.Entity<Registration>().Property(t => t.ParticipantId)
    .HasColumnAnnotation(
        IndexAnnotation.AnnotationName,
        new IndexAnnotation(
            new IndexAttribute(uniqueIndex)
            {
                IsUnique = true,
                Order = 2
            }
        )
    );