Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed-length string column in Code First Migrations

I'm creating an Entity Framework 6 model using Code First Migrations, and I want a column in the resulting database to be fixed-length instead of variable-length; furthermore, I want to do this in a DBMS-agnostic way.

The ConventionPrimitivePropertyConfiguration.IsFixedLength method seemed built for this purpose. I couldn't find an existing attribute that used it, so I made one myself, like so:

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Configuration;
using System.Data.Entity.ModelConfiguration.Conventions;

class FixedLengthAttribute : Attribute { }

class FixedLengthAttributeConvention
    : PrimitivePropertyAttributeConfigurationConvention<FixedLengthAttribute>
{
    public override void Apply(ConventionPrimitivePropertyConfiguration configuration,
        FixedLengthAttribute attribute)
    {
        configuration.IsFixedLength();
    }
}

class MyModel : DbContext
{
    internal virtual DbSet<MyEntity> MyEntities { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new FixedLengthAttributeConvention());
    }
}

class MyEntity
{
    [Key, FixedLength, StringLength(10)]
    public string MyStringProperty { get; set; }
}

However, when running Add-Migration using this code, the line that defines that database column in the resulting migration file (MyStringProperty = c.String(nullable: false, maxLength: 10)) doesn't say anything about fixed length. And when I run this migration on a database I get an NVARCHAR column.

What am I doing wrong here?

like image 606
Taymon Avatar asked Apr 15 '26 22:04

Taymon


2 Answers

The StringLength attribute appears to be overwritting the FixedLength attribute. A workaround is to add the length property to your FixedLength attribute and set the HasMaxLength yourself

class FixedLengthAttribute : Attribute 
{ 
    public int Length { get; set; }
}


public override void Apply(ConventionPrimitivePropertyConfiguration configuration,
        FixedLengthAttribute attribute)
{
    configuration.IsFixedLength();
    configuration.HasMaxLength(attribute.Length);
}

class MyEntity
{
    [Key, FixedLength(Length=10)]
    public string MyStringProperty { get; set; }
}
like image 92
Aducci Avatar answered Apr 17 '26 11:04

Aducci


An to alternative to Aducci's answer is to use the ColumnAttribute to specify the datatype for the column:

class MyEntity
{
    [Key]
    [MaxLength(10)]
    [Column(TypeName = "nchar")]
    public string MyEntityId { get; set; }
}

This leads to column in the table:

MyEntityId nchar(10) NOT NULL PRIMARY KEY

Personally, I believe this method preferable, as it does not require overriding the DbContext's Apply function.

like image 27
AxelEckenberger Avatar answered Apr 17 '26 10:04

AxelEckenberger