Entity Framework Core 3.1的Code First唯一约束不起作用

4

问题很明确。这是我在 dbContext 类中的 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" });
}

这是我生成表格的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

正如你所看到的,这些列不是唯一的且可为空。

我在这里漏掉了什么?


你想让状态和代码都是唯一的,还是只有代码? - A_kat
我希望状态和代码都是唯一的。 - Sanjay Kumar
2个回答

3

使用流畅的语法:

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 Server查询:

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]);

3

首先,由于您希望列和状态代码不可为空,因此需要使用注释[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上看到的那样,索引已经被创建。 enter image description here 但是,我的脚本表当然不包括该索引。我们不创建约束,而是创建索引,索引不包括在创建表脚本中。

谢谢您的回答,但我已经尝试过了,它并没有起作用。 - Sanjay Kumar
使用RequiredAttribute,你的列StateCode是可空的吗? - vernou
1
@Orwel 不是的,这实际上是一个旧的迁移。我没有重新应用迁移,犯了错。 - A_kat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接