Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add discriminator column as a part of a unique index in Entity Framework

Is it possible using EF Fluent API to configure a Discriminator column and another string column to be part of a unique index constraint?

I have a list of identifiers, where the identifiers can be of different types. Each identifier has a property of type string which holds the identifying string.

A customer in my case can ha different identifiers. But there can only be one identifier with unique string per discriminator.

Abstract class defining a identifier type

 public abstract class CustomerIdentifier : Entity<int>
 {
    public string Identifier { get; set; }
 }

Concrete class derived from CustomerIdentifier

 class NationalIdNumberIdentifier : CustomerIdentifier
 {
 }

I've managed to configure index for the string column using the answer here, Unique Key constraints for multiple columns in Entity Framework as follows

class CustomerIdentifierMap : EntityTypeConfiguration<CustomerIdentifier>
{
    public CustomerIdentifierMap()
    {
        Property(p => p.Identifier).HasMaxLength(100).IsRequired().HasUniqueIndexAnnotation("UQ_IdentifierPerDiscriminator", 0);
    }
}

I need to somehow add another line here specifiying that the discrimnator should be included in the unique index constraint.

like image 896
honk Avatar asked Jan 26 '15 15:01

honk


1 Answers

Actually it can be done in EF 6. Below is an example that uses the primary key to create a unique index.

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

}
like image 82
realstrategos Avatar answered Sep 28 '22 23:09

realstrategos