如何使用EF fluentApi并设置一个具有2个不同外键的复合键的类

本文关键字:2个 复合 一个 fluentApi EF 何使用 设置 | 更新日期: 2023-09-27 17:58:06

我在这里发现了一些类似的问题,但没有一个问题是对我有用的。

我有一个项目,有大约60个实体,有很多场景,所有这些都通过简单使用一些基本的EF注释映射到数据库。一个我无法付诸实施的场景是:

public class Client {
  [Key]
  public int IDClient { get; set; }
  (...)
}
public class Research {
  [Key]
  public int IDReasearch { get; set; }
  (...)
}
public class ClientReaserach {
  [Key, Column(Order = 1)]
  public int IDClient { get; set; }
  [ForeignKey("IDClient")]
  public virtual Client Client { get; set; }
  [Key, Column(Order = 2)]
  public int IDResearch { get; set; }
  [ForeignKey("IDResearch")]
  public virtual Research Research { get; set; }
  (...)
}

尽管这看起来像是迄今为止行之有效的其他场景,但在我看来,这一场景就像是一种fluentAPI类型的东西(据我所知,注释只给了我EF实际能力的子集)。

所以我有一些问题:

  • 我可以继续使用我的注释并使用fluentAPI仅映射上述情况吗?

  • EF如何"知道"这些实体及其关系是通过fluentAPI映射的(并且在我添加新的迁移时不会再次尝试映射它们)?

  • 使用fluentAPI重新构建我的所有项目可以吗?我应该如何处理已经生成的所有迁移(我应该删除它们吗)?

  • 我将如何通过fluentAPI实现上述场景?

编辑1:

这是我用来完成上述场景的真实代码,如下所示:

public class PacientePesquisa
{
    [Key, Column(Order = 1)]
    [Required(ErrorMessage = Msg_Critica_Req_IDPesquisa)]
    [Display(Name = "Pesquisa")]
    public int IDPesquisa { get; set; }
    [ForeignKey("IDPesquisa")]
    public virtual Pesquisa Pesquisa { get; set; }
    [Key, Column(Order = 2)]
    [Required(ErrorMessage = Msg_Critica_Req_NRProntuario)]
    [StringLength(NRProntuario_MaxLength, ErrorMessage = Msg_Critica_Tam_NRProntuario)]
    [Display(Name = "Prontuário")]
    public string NRProntuario { get; set; }
    [ForeignKey("NRProntuario")]
    public virtual Paciente Paciente { get; set; }
    (...)

public class Pesquisa 
{
    [Key]
    public int IDPesquisa { get; set; }
    (...)
public class Paciente 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public string NRProntuario { get; set; }
    (...)

当运行"添加迁移"时,我收到以下错误:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Data.Entity.ModelConfiguration.ModelValidationException: One or more validation errors were detected during model generation:
System.Data.Entity.Edm.EdmAssociationConstraint: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.        

如何使用EF fluentApi并设置一个具有2个不同外键的复合键的类

我将尝试回答您的问题,但有一个问题是:带注释的映射有什么问题?这看起来很好,我不认为需要Fluent API。在这个答案中是一个类似的模型("与有效负载的多对多关系"),它只使用注释和映射约定,而不使用任何Fluent API映射。

关于您的问题:

我可以继续使用我的注释并使用fluentAPI仅映射上述情况?

是的,您可以通过数据注释和Fluent API混合映射,而不会出现问题-只要您不创建矛盾的映射,例如将带有注释的列重命名为与Fluent API不同的名称。

EF将如何"知道"这些实体及其关系通过fluentAPI映射(并且在添加时不要再次尝试映射它们新的迁移)?

EF处理上下文的OnModelCreating方法,并应用您定义的映射。它还处理注释并应用在那里定义的映射。它将两个映射合并到一个模型中。此模型被序列化为"模型散列",该散列存储在数据库的MigrationHistory表中。如果模型散列与已经存储的最新散列值相同,则EF知道模型和数据库是同步和最新的,并且不会创建新的迁移。

使用fluentAPI重新构建我的所有项目可以吗?我该怎么办已经生成了所有迁移(我应该删除吗他们)?

是的,没关系。没有必要删除旧的迁移。使用Fluent API添加一个新的映射只是实体模型的一个新发展——就像添加新的注释一样。

我将如何通过fluentAPI实现上述场景?

modelBuilder.Entity<ClientResearch>()
    .HasKey(cr => new { cr.IDClient, cr.IDResearch });
modelBuilder.Entity<ClientResearch>()
    .HasRequired(cr => cr.Client)
    .WithMany() // or .WithMany(c => c.ClientResearches) if you have a collection
    .HasForeignKey(cr => cr.IDClient);
modelBuilder.Entity<ClientResearch>()
    .HasRequired(cr => cr.Research)
    .WithMany() // or .WithMany(r => r.ClientResearches) if you have a collection
    .HasForeignKey(cr => cr.IDResearch);