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]);
嗯,问题很清楚了。这是我在 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]);