使用 Fluent Api 时复合键 EF Core 出现错误

Posted

技术标签:

【中文标题】使用 Fluent Api 时复合键 EF Core 出现错误【英文标题】:Composite Key EF Core getting error when using Fluent Api 【发布时间】:2017-09-28 10:03:01 【问题描述】:

所以我在 Entity Framework Core 中有以下类。我正在尝试进行代码优先迁移,但我一生都无法弄清楚如何为这项工作制作流畅的 API。

public class Participants

    public Activity Activity  get; set;  //Class with Id and Name of Activity
    public ApplicationUser Participant  get; set;  

    [Key]
    [Column(Order = 1)]
    public int ActivityId  get; set; 


    [Key]
    [Column(Order = 2)]
    public string ParticipantId  get; set; 

在 EF6 中,我能够在 OnModelCreating 中执行此操作以使其正常工作。

 modelBuilder.Entity<Attendance>()
            .HasRequired(a => a.Activity)
            .WithMany()
            .WillCascadeOnDelete(false);

但是在 EF Core 中我得到了

" 实体类型 'Participants' 具有使用数据注释定义的复合主键。要设置复合主键,请使用 fluent API。"

我尝试过使用

modelBuilder.Entity<Participants>().HasKey(p => new p.Activity, p.Participant);

但是,这只会导致

在表“参与者”上引入 FOREIGN KEY 约束“FK_Participants_AspNetUsers_ParticipantId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

如果有更好的方法来完成整个事情,我愿意接受建议。如果您订阅了复数视力,我基本上是想让 Mosh Hamedani 的“成为全栈开发人员”在 EF 核心中工作。该示例位于“13-full-stack-fundamentals”文件夹中。

更新:也尝试过

        modelBuilder.Entity<Participants>()
            .HasOne(p => p.Activity)
            .WithMany()
            .OnDelete(DeleteBehavior.Cascade);

还有

“实体类型'Participants'具有使用数据注释定义的复合主键。要设置复合主键,请使用流式API。”

更新 2:在尝试了 Roy 的建议后,这就是我得到的

在表“参与者”上引入 FOREIGN KEY 约束“FK_Participants_AspNetUsers_ParticipantId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。

更新 3:在迁移中

我删除了 OneDelete: ReferntialAction.Cascade 之一,它起作用了。我删除了 FK_Participants_AspNetUsers_ParticipantId 的一项。

我的 OnModelCreating 也改成了这个

        modelBuilder.Entity<Participants>()
            .HasKey(p => new  p.ActivityId, p.ParticipantId );
        base.OnModelCreating(modelBuilder);

        //Added this ( Not sure if it's needed if anyone knows let me know) 
        modelBuilder.Entity<Participants>()
            .HasOne(p => p.Activity)
            .WithMany()
            .OnDelete(DeleteBehavior.Cascade);

【问题讨论】:

如果您以类似于 modelBuilder.Entity() .HasRequired(a => a.Activity) .WithMany() 的方式定义参与者和 ApplicationUser(参与者)之间的关系会发生什么。 WillCascadeOnDelete(false); ? 已更新以显示我尝试过的其他内容。 你能分享Activity类型吗?您确定您没有引入循环路径吗?如果是这种情况,那么您不需要从迁移中删除任何内容。 【参考方案1】:

您要做的是在 Activity 和 Participant 之间创建一种关系,这在 EFCore 中略有不同。

为此,您需要在模型构建器中引用 ForeignKey 属性而不是 NavigationProperties,如下所示:

    modelBuilder.Entity<Participants>()
        .HasKey(p => new  p.ActivityId , p.ParticipantId );

【讨论】:

@vgwizardx 不理解您的更新,您的更改是否解决了问题? 是的,他们修复了我进行更改后发生的问题。我猜迁移中发生的事情是它创建了一个双级联路径。因此,您必须删除其中一个级联路径才能使事情完全正常。 虽然这个答案可能已经解决了问题,但推理不正确。 EF 核心不允许使用数据注释的复合 PK 定义,必须使用 fluent API 指定。无论任何导航或关系如何,都是如此。上述代码中,即使没有导航,仍然会抛出复合PK异常。

以上是关于使用 Fluent Api 时复合键 EF Core 出现错误的主要内容,如果未能解决你的问题,请参考以下文章

是否有使用 Fluent API 的 C# EF6 DbContext 生成器?

如何在 EF Core 中通过 Fluent Api 创建加密列

EF Core Fluent API

EF Fluent API上

EF Fluent Api 是不是可以设置最小长度?

使用 EF4.1 Fluent API 将具有导航属性的实体拆分为两个表