Entity framework core 实体框架核心3.1代码优先唯一约束不起作用
这个问题很清楚。下面是我在Entity framework core 实体框架核心3.1代码优先唯一约束不起作用,entity-framework-core,code-first,unique-constraint,Entity Framework Core,Code First,Unique Constraint,这个问题很清楚。下面是我在dbContext类中的OnModelCreating方法: modelBuilder.Entity<States>(entity => { entity.ToTable("States"); modelBuilder.Entity<States>() .HasIndex(p => new { p.State })
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();
下面是我对正在生成的表的SQL查询:
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" });
}
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
正如您所看到的,这些列不是唯一的,可以为null
我这里缺少什么?首先,由于您希望列和状态代码不可为空,因此需要使用注释声明它
[必需]
:
[Required]
public string Code {get;set;}
[Required]
public string State {get;set;}
以上内容将使列不可为空
列的唯一组合:
entity
.HasIndex(p => new { p.State, p.Code })
.IsUnique();
以上是唯一的办法。为了使列的组合唯一,必须对这两个列进行索引。包含的属性将不起作用。我还删除了HasFilter,因为该列现在是不可为null的。只获取非null结果的筛选器没有任何用处
编辑:
每列都是唯一的
对于每一列,您也遵循相同的逻辑。现在需要2个索引,而不是1个索引
entity
.HasIndex(p => p.State)
.IsUnique();
entity
.HasIndex(p => p.Code)
.IsUnique();
正如您在SQL Management Studio上看到的,索引已经创建。
当然,我的脚本表不包括索引。我们不创建约束,而是创建索引,索引不包括在创建表脚本中。使用流畅的语法:
公共类状态
{
公共int Id{get;set;}
公共字符串代码{get;set;}
公共字符串状态{get;set;}
}
公共类MyContext:DbContext
{
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
基本配置(选项生成器);
optionsBuilder.UseSqlServer(“***”);
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
//声明不可为空的列
modelBuilder.Entity().Property(s=>s.Code.IsRequired();
modelBuilder.Entity().Property(s=>s.State.IsRequired();
//添加唯一性约束
modelBuilder.Entity().HasIndex(s=>s.Code).IsUnique();
modelBuilder.Entity().HasIndex(s=>s.State).IsUnique();
}
}
生成的迁移代码:
protected override void Up(MigrationBuilder MigrationBuilder)
{
migrationBuilder.CreateTable(
名称:“国家”,
列:表=>new
{
Id=table.Column(可空:false)
.Annotation(“SqlServer:Identity”、“1,1”),
代码=table.Column(可空:false),
State=table.Column(可空:false)
},
约束:表=>
{
表.PrimaryKey(“PK_状态”,x=>x.Id);
});
migrationBuilder.CreateIndex(
名称:“IX_状态_代码”,
表:“国家”,
栏目:“代码”,
独特:正确);
migrationBuilder.CreateIndex(
名称:“九州”,
表:“国家”,
专栏:“国家”,
独特:正确);
}
以及SQL Server查询:
创建表[状态](
[Id]int不是空标识,
[代码]nvarchar(最大值)不为空,
[状态]nvarchar(450)不为空,
约束[PK_States]主键([Id])
);
在[States]([State])上创建唯一索引[IX_States\u State];
在[States]([Code])上创建唯一索引[IX_States_Code];
您希望状态和代码是唯一的,还是只希望代码是唯一的?我希望状态和代码都是唯一的。谢谢您的回答,但我已经尝试过了,但它不起作用。使用requiredAttribute
时,您的列state
和code
可以为空?@或者不可以。这实际上是一个旧的迁移。我没有重新应用迁移的错误。