在 Entity Framework 中添加鉴别器列作为唯一索引的一部分
Add discriminator column as a part of a unique index in Entity Framework
是否可以使用 EF Fluent API 将鉴别器列和另一个字符串列配置为唯一索引约束的一部分?
我有一个标识符列表,其中标识符可以是不同类型的。每个标识符都有一个 属性 类型的字符串,其中包含标识字符串。
在我的例子中,一个客户可以有不同的标识符。但是每个鉴别器只能有一个具有唯一字符串的标识符。
摘要class定义标识符类型
public abstract class CustomerIdentifier : Entity<int>
{
public string Identifier { get; set; }
}
从 CustomerIdentifier
派生的具体 class
class NationalIdNumberIdentifier : CustomerIdentifier
{
}
我已经使用这里的答案为字符串列配置了索引,
Unique Key constraints for multiple columns in Entity Framework如下
class CustomerIdentifierMap : EntityTypeConfiguration<CustomerIdentifier>
{
public CustomerIdentifierMap()
{
Property(p => p.Identifier).HasMaxLength(100).IsRequired().HasUniqueIndexAnnotation("UQ_IdentifierPerDiscriminator", 0);
}
}
我需要以某种方式在此处添加另一行,指定鉴别器应包含在唯一索引约束中。
不幸的是,它在 EF 6 中不受支持,根据 "Support of Discriminator column which is part of Primary key" https://entityframework.codeplex.com/workitem/2420.
可能包含在 EF 7 中
您可能想对其进行投票以将其推到优先级列表中。
实际上在EF 6中可以做到。下面是一个使用主键创建唯一索引的例子。
internal class DiscriminatorServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
const string DiscriminatorColumnName = "Discriminator";
protected override void Generate(CreateTableOperation op)
{
base.Generate(op);
if (op.Columns.Any(x => x.Name == DiscriminatorColumnName))
{
if (op.PrimaryKey != null && op.PrimaryKey.Columns.Any())
{
CreateDiscriminatorIndex(op.Name, true, op.PrimaryKey.Columns.ToArray());
}
else
{
CreateDiscriminatorIndex(op.Name);
}
}
}
private void CreateDiscriminatorIndex(string tableName, bool isUnique = false, params string[] columns)
{
var cols = "[Discriminator]";
if (columns.Length > 0)
{
cols += ", " + string.Join(", ", columns.Select(x => "[" + x + "]"));
}
var unique = isUnique ? "UNIQUE" : "";
using (var writer = Writer())
{
var str = $@"
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Discriminator' AND object_id = OBJECT_ID(N'{tableName}'))
EXECUTE('CREATE {unique} NONCLUSTERED INDEX [IX_Discriminator] ON {tableName} ({cols})')";
writer.WriteLine(str);
Statement(writer);
}
}
}
EF 7 现在使用流畅的 API:
对此提供支持
modelBuilder.Entity<User>()
.HasIndex("EmailAddress", "Discriminator")
.HasName("UQ_EmailAddress")
.IsUnique();
我没有使用 EF 检查,但使用 EF core 进行了验证。我们需要在 base table 中为 Discriminator 添加一个自定义的 属性 然后我们可以在 HasIndex
方法中使用这个 属性 来制作唯一键。我已经用 Oracle 和 SQLServer 验证了它。
代码:
鉴别器的自定义 属性:
public string TableName { get; set; }
流利API:
modelBuilder.Entity<BaseTable>().HasDiscriminator<string>("TableName").HasValue<ChildTable1>("ChildTable1").HasValue<ChildTable2>("ChildTable2").HasValue<ChildTable3>("ChildTable3");
modelBuilder.Entity<BaseTable>().HasIndex(m => new { m.Name, m.DeletedOnUtc, m.TableName }).IsUnique().HasFilter(null);
是否可以使用 EF Fluent API 将鉴别器列和另一个字符串列配置为唯一索引约束的一部分?
我有一个标识符列表,其中标识符可以是不同类型的。每个标识符都有一个 属性 类型的字符串,其中包含标识字符串。
在我的例子中,一个客户可以有不同的标识符。但是每个鉴别器只能有一个具有唯一字符串的标识符。
摘要class定义标识符类型
public abstract class CustomerIdentifier : Entity<int>
{
public string Identifier { get; set; }
}
从 CustomerIdentifier
派生的具体 class class NationalIdNumberIdentifier : CustomerIdentifier
{
}
我已经使用这里的答案为字符串列配置了索引, Unique Key constraints for multiple columns in Entity Framework如下
class CustomerIdentifierMap : EntityTypeConfiguration<CustomerIdentifier>
{
public CustomerIdentifierMap()
{
Property(p => p.Identifier).HasMaxLength(100).IsRequired().HasUniqueIndexAnnotation("UQ_IdentifierPerDiscriminator", 0);
}
}
我需要以某种方式在此处添加另一行,指定鉴别器应包含在唯一索引约束中。
不幸的是,它在 EF 6 中不受支持,根据 "Support of Discriminator column which is part of Primary key" https://entityframework.codeplex.com/workitem/2420.
可能包含在 EF 7 中您可能想对其进行投票以将其推到优先级列表中。
实际上在EF 6中可以做到。下面是一个使用主键创建唯一索引的例子。
internal class DiscriminatorServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
const string DiscriminatorColumnName = "Discriminator";
protected override void Generate(CreateTableOperation op)
{
base.Generate(op);
if (op.Columns.Any(x => x.Name == DiscriminatorColumnName))
{
if (op.PrimaryKey != null && op.PrimaryKey.Columns.Any())
{
CreateDiscriminatorIndex(op.Name, true, op.PrimaryKey.Columns.ToArray());
}
else
{
CreateDiscriminatorIndex(op.Name);
}
}
}
private void CreateDiscriminatorIndex(string tableName, bool isUnique = false, params string[] columns)
{
var cols = "[Discriminator]";
if (columns.Length > 0)
{
cols += ", " + string.Join(", ", columns.Select(x => "[" + x + "]"));
}
var unique = isUnique ? "UNIQUE" : "";
using (var writer = Writer())
{
var str = $@"
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_Discriminator' AND object_id = OBJECT_ID(N'{tableName}'))
EXECUTE('CREATE {unique} NONCLUSTERED INDEX [IX_Discriminator] ON {tableName} ({cols})')";
writer.WriteLine(str);
Statement(writer);
}
}
}
EF 7 现在使用流畅的 API:
对此提供支持modelBuilder.Entity<User>()
.HasIndex("EmailAddress", "Discriminator")
.HasName("UQ_EmailAddress")
.IsUnique();
我没有使用 EF 检查,但使用 EF core 进行了验证。我们需要在 base table 中为 Discriminator 添加一个自定义的 属性 然后我们可以在 HasIndex
方法中使用这个 属性 来制作唯一键。我已经用 Oracle 和 SQLServer 验证了它。
代码: 鉴别器的自定义 属性:
public string TableName { get; set; }
流利API:
modelBuilder.Entity<BaseTable>().HasDiscriminator<string>("TableName").HasValue<ChildTable1>("ChildTable1").HasValue<ChildTable2>("ChildTable2").HasValue<ChildTable3>("ChildTable3");
modelBuilder.Entity<BaseTable>().HasIndex(m => new { m.Name, m.DeletedOnUtc, m.TableName }).IsUnique().HasFilter(null);