Entity Framework 核心 3.1 代码第一个唯一约束不起作用

Entity Framework Core 3.1 code first unique constraint not working

嗯,问题很清楚了。这是我在 dbContext class:

中的 OnModelCreating 方法
modelBuilder.Entity<States>(entity =>
            {
                entity.ToTable("States");

                modelBuilder.Entity<States>()
                .HasIndex(p => new { p.State })
                .HasFilter("[State] IS NOT NULL")
                .HasFilter("[Code] IS NOT NULL")
                .IncludeProperties(p => new
                {
                    p.Code
                })
                .IsUnique();

我也试过.IsUnique(true)但是没用。

这是正在生成的迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{
        migrationBuilder.CreateTable(
            name: "States",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                State = table.Column<string>(maxLength: 30, nullable: true),
                Code = table.Column<string>(maxLength: 3, nullable: true),
                Description = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_States", x => x.Id);
            });

        migrationBuilder.CreateIndex(
            name: "IX_States_State",
            table: "States",
            column: "State",
            unique: true,
            filter: "[Code] IS NOT NULL")
            .Annotation("SqlServer:Include", new[] { "Code" });
}

这是我对正在生成的 table 的 SQL 查询:

CREATE TABLE [dbo].[States]
(
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    [State] [NVARCHAR](30) NULL,
    [Code] [NVARCHAR](3) NULL,
    [Description] [NVARCHAR](MAX) NULL,

    CONSTRAINT [PK_States] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

如您所见,列不是唯一的并且可以为空。

我在这里错过了什么?

首先,由于您希望列和状态代码不可为空,因此您需要使用注释 [Required]:

进行声明
[Required]
public string Code {get;set;}

[Required]
public string State {get;set;}

以上将使列不可为空。

唯一的列组合:

entity
    .HasIndex(p => new { p.State, p.Code })
    .IsUnique();

以上是唯一的方法。为了使列的组合唯一,您必须对它们都进行索引。包含的属性将不起作用。我还删除了 HasFilter,因为该列现在不可为空,仅获取非空结果的过滤器没有用。

编辑:

每一列都是唯一的

对于每一列,您也遵循相同的逻辑。现在您需要 2 个索引而不是 1 个。

entity
    .HasIndex(p => p.State)
    .IsUnique();

entity
    .HasIndex(p => p.Code)
    .IsUnique();

如您在 SQL Management Studio 中所见,索引已创建。

当然我的脚本 table 不包括索引。我们不创建约束我们创建索引并且索引不包含在创建 table 脚本中。

语法流畅:

public class States
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string State { get; set; }
}

public class MyContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer("***");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //Declare non nullable columns
        modelBuilder.Entity<States>().Property(s => s.Code).IsRequired();
        modelBuilder.Entity<States>().Property(s => s.State).IsRequired();
        //Add uniqueness constraint
        modelBuilder.Entity<States>().HasIndex(s => s.Code).IsUnique();
        modelBuilder.Entity<States>().HasIndex(s => s.State).IsUnique();
    }
}

已生成迁移代码:

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "States",
        columns: table => new
        {
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:Identity", "1, 1"),
            Code = table.Column<string>(nullable: false),
            State = table.Column<string>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_States", x => x.Id);
        });

    migrationBuilder.CreateIndex(
        name: "IX_States_Code",
        table: "States",
        column: "Code",
        unique: true);

    migrationBuilder.CreateIndex(
        name: "IX_States_State",
        table: "States",
        column: "State",
        unique: true);
}

并且 SQL 服务器查询:

CREATE TABLE [States] (
    [Id] int NOT NULL IDENTITY,
    [Code] nvarchar(max) NOT NULL,
    [State] nvarchar(450) NOT NULL,
    CONSTRAINT [PK_States] PRIMARY KEY ([Id])
);
CREATE UNIQUE INDEX [IX_States_State] ON [States] ([State]);
CREATE UNIQUE INDEX [IX_States_Code] ON [States] ([Code]);