C# EF 6.1唯一可空索引
在EF 6.1中,首先使用代码,您可以使用实体中的属性或使用fluent API创建索引,如下所示:C# EF 6.1唯一可空索引,c#,sql-server,entity-framework,ef-code-first,C#,Sql Server,Entity Framework,Ef Code First,在EF 6.1中,首先使用代码,您可以使用实体中的属性或使用fluent API创建索引,如下所示: Property(x => x.PropertyName) .IsOptional() .HasMaxLength(450) .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttri
Property(x => x.PropertyName)
.IsOptional()
.HasMaxLength(450)
.HasColumnAnnotation("Index",
new IndexAnnotation(new IndexAttribute("IX_IndexName") {IsUnique = true, }));
是否有任何方法可以像在SQL Server本机中一样(请参阅:)说scaffold
WHERE PropertyName不为NULL
?我没有找到方法告诉EF使用WHERE子句,但这里有一些解决方法。检查它是否适合你的情况
Up
方法中创建的DbMigration类中,运行sql以创建唯一的可空索引Down
方法并在内部使用DropIndex
方法:
DropIndex(tableName, indexName);
此外,如果数据库中已有可能与唯一索引约束冲突的数据,则可能需要一些附加代码
注意:这里您可以使用CreateIndex方法,但我无法使用它创建正确的索引。请忽略我的匿名论点,否则我会把它们写错。你可以自己试一试,把结果写在这里。语法如下:
CreateIndex(
table: "dbo.ExampleClasses",
columns: new string[] { "UniqueColumn" },
unique: true,
name: "IX_UniqueColumn",
clustered: false,
anonymousArguments: new
{
Include = new string[] { "UniqueColumn" },
Where = "UniqueColumn IS NOT NULL"
});
5尝试为唯一列和其他相等值添加两个具有空值的度量值
这是我的演示代码-在EF Core中,您可以使用fluent API中的HasFilter方法来实现您想要的功能,而无需向迁移中添加自定义SQL
builder.Entity<Table>()
.HasIndex(x => x.PropertyName)
.HasName("IX_IndexName")
.HasFilter("PropertyName IS NOT NULL");
否,您不能以本机方式执行此操作 但我创建了一个自定义SQL生成器,它支持以下功能:
ASC
或DESC
WHERE
关键字的使用:
分为三部分。这些部分是:
Column1
进行排序ASC
和Column2
DESC
,并且需要一个where
子句,您的索引名称将是:
var uniqueName = "UN_MyIndex:ASC,DESC:Column1 IS NOT NULL";
你可以这样简单地使用它:
migrationBuilder.CreateIndex(
name: "IX_IndexName",
table: "Table",
columns: new[] { "PropertyName" },
filter: "PropertyName IS NOT NULL");
Property(t => t.Column1)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute(uniqueName) { IsUnique = true, Order = 1 }));
Property(t => t.Column2)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute(uniqueName) { IsUnique = true, Order = 2 }));
然后,在Configuration.cs
文件中,在构造函数中添加以下行:
SetSqlGenerator("System.Data.SqlClient", new CustomSqlServerMigrationSqlGenerator());
最后,创建
CustomSqlServerMigrationSqlGenerator.cs
文件,如图所示:。根据Viktor的回答,我提出了自动创建此代码的解决方案
最终迁移文件不应使用CreateIndex
方法,而应使用我命名的CreateIndexNullable
方法。我在DbMigrationEx
中创建的这个方法扩展了DbMigration
protected void CreateIndexNullable(string table, string column, string name)
{
Sql($@"CREATE UNIQUE NONCLUSTERED INDEX [{name}] ON {table}([{column}] ASC) WHERE([{column}] IS NOT NULL);");
}
如何更改迁移类代码
在我设置的迁移文件夹中创建的配置
类中
CodeGenerator = new CSharpMigrationCodeGeneratorIndexNullable();
MyCSharpMigrationCodeGeneratorIndexNullable
类扩展了CSharpMigrationCodeGenerator
。
我不会展示确切的课堂内容,我只是展示一下想法。
基于CSharpMigrationCodeGenerator
内容,我覆盖了一些方法。实体框架项目可访问
要将迁移类更改为dbmigtorionex
,我使用了
Generate(IEnumerable<MigrationOperation> operations, string @namespace, string className)
Generate(CreateIndexOperation createIndexOperation, IndentedTextWriter writer)
要将迁移方法更改为CreateIndexNullable
I使用了
Generate(IEnumerable<MigrationOperation> operations, string @namespace, string className)
Generate(CreateIndexOperation createIndexOperation, IndentedTextWriter writer)
你需要换行
writer.Write("CreateIndex(");
也
到
但如何知道索引是否必须为空
createIndexOperation
参数包含索引信息。我无法修改CreateIndexOperation
创建,但其表
、名称
和列
属性足以访问实体类中的字段并获得可扩展的索引
属性。谢谢Viktor!它对我非常有效。另一方面,“anonymousArguments”依赖于提供程序,SQL Server忽略它。创建索引解决方案不起作用。我希望您删除它,因为它在一开始就让我感到困惑。谢谢ViktorReally,很遗憾匿名争论方法不起作用。似乎也缺少相关的文档。支持哪些值等。如果表名恰好是保留字,则必须对其进行转义,例如tableName=“dbo.\'User\”代码>(至少对于SQL Server)很好!不要忘了创建降级,好的。上面的语句中似乎缺少了..IsUnique()
WriteIndexParameters(createIndexOperation, writer);
writer.Write(", ");
writer.Write(Quote(createIndexOperation.Name));