EF Core复合键,一个外置,一个自动递增

本文关键字:一个 EF 复合 Core | 更新日期: 2023-09-27 18:02:26

我有这个实体:

public class PlayerScoreHistory
{
    public int Id { get; set; }
    public int PlayerScoreId { get; set; }
    public DateTime ScoreWhen { get; set; }
}

我需要从这两个Id字段中生成一个复合键。PlayerScoreId需要是PlayerScore.Id的外键。Id需要是一个自动递增的id。

所以,我得到了:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<PlayerScoreHistory>()
        .HasKey(x => new { x.Id, x.PlayerScoreId });
}

这给了我组合键。我做了Add-Migration Initial来给我初始的迁移。

为了获得外键,我只需在constraints参数中添加一行:
 migrationBuilder.CreateTable(
    name: "PlayerScoreHistories",
    columns: table => new
        {
            Id = table.Column<int>(nullable: false),
            PlayerScoreId = table.Column<int>(nullable: false),
            ScoreWhen = table.Column<DateTime>(nullable: false)
        },
    constraints: table =>
        {
            table.PrimaryKey("PK_PlayerScoreHistories", x => new { x.Id, x.PlayerScoreId });
            table.ForeignKey("FK_PlayerScoreId", arg => new {  arg.PlayerScoreId}, "PlayerScores", "Id");
        });

两个问题:

  1. 如何在OnModelCreating方法中获得外键创建?
  2. 我如何使Id列数据库生成字段,并确保EF核心不尝试设置值?

我不确定有什么选择对我开放,因为EF Core是非常新的…

我得到的两个错误:

1。

当我将这行添加到Id column参数配置中时:

Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn)

当IDENTITY_INSERT设置为OFF时,SQL无法在表' table '中插入标识列的显式值[duplicate]

2。

当我删除一行然后尝试添加一个实体时,我得到:

Id列不能插入null


显然我在某处....


编辑至今

我决定删除Id列,只使用PlayerScoreIdScoreWhen作为复合键....

但是,我仍然有一个问题是如何使OnModelCreating身份PlayerScoreId作为外键-没有导航属性.....

EF Core复合键,一个外置,一个自动递增

但是,我仍然有一个问题是如何使OnModelCreating身份PlayerScoreId作为一个外键-没有导航属性.....

您可以使用HasOne/WithMany(或HasMany/WithOne)方法而不指定导航属性,像往常一样与HasForeignKey结合使用:

modelBuilder.Entity<PlayerScoreHistory>()
    .HasOne<PlayerScore>()
    .WithMany()
    .HasForeignKey(e => e.PlayerScoreId);

首先,编辑迁移文件为您提供所需的数据库,但是EF运行时将不知道这些更改。运行时需要的所有信息应该只在模型中配置。

因此得到exception

当IDENTITY_INSERT设置为OFF时,SQL无法在表' table '中插入标识列的显式值[duplicate]

因为EF运行时不知道标识列,所以它将发送0 (default(int))作为插入语句中标识列的值。

我不能得到第二个异常,因为EF不会(&不能)尝试为int类型属性插入空,因为值在c#世界中不能为空。

现在回答你的问题:

  1. Ivan的答案是正确的。这就是在modelbuilder中配置外键的方法。

    modelBuilder.Entity<PlayerScoreHistory>()
        .HasOne<PlayerScore>()
        .WithMany()
        .HasForeignKey(e => e.PlayerScoreId);
    

有关如何配置关系的更多信息- https://ef.readthedocs.io/en/latest/modeling/relationships.html

  • 要告诉Id是数据库生成的字段,在modelbuilder中使用以下代码:

    modelBuilder
        .Entity<PlayerScoreHistory>()
        .Property(e => e.Id)
        .ValueGeneratedOnAdd();
    
  • 这将告诉EF在插入实体时生成Id的值,如果为ValueGeneratedOnAdd配置了1个整数列,则在SqlServer上将其转换为Identity。有关生成属性的更多信息,请访问https://ef.readthedocs.io/en/latest/modeling/generated-properties.html#value-generated-on-add