The nvarchar data type requires twice as much space to store as an equivalent-length varchar. For that reason, it is usually recommended to use varchar when you don't have a requirement to store Unicode characters.

Entity Framework Core automatically uses the nvarchar data type for strings, unless the column type is explicitly set, or .IsUnicode(false) is set in OnModelCreating(). If you want string columns to default to varchar, and you don't care to explicitly set a column type (or set .IsUnicode(false)) for every single string in your model, then you're either smart, lazy, or both. Speaking of lazy, here is how I automate this for myself in Entity Framework Core 3.1:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

    // Other modelBuilder stuff here

    // Force all string-based columns to non-unicode equivalent 
    // when no column type is explicitly set.
    foreach (var property in modelBuilder.Model.GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .Where(
               p => p.ClrType == typeof(string)    // Entity is a string
            && p.GetColumnType() == null           // No column type is set
        ))
    {
        property.SetIsUnicode(false);
    }

}

I haven't really analyzed the benefits or drawbacks of inserting this before or after other model changes in OnModelCreating(), but I imagine it would interfere with any other code you have in there that checks or alters column types. So tweaking & testing may be required.

Changes Required if Using ASP.Net Identity

If you are using ASP.Net Identity in your project, you need a couple of additions to this code. Calling base.OnModelCreating(modelBuilder); is usually (always?) required when overriding OnModelCreating() in a project that uses ASP.Net Identity. Also, an additional line in the .Where() function filters out entities belonging to tables used by Identity. (ASP.Net Identity table names start with 'AspNet'.) In a test project which uses ASP.Net Identity, I found that my migrations could not be applied to the database because they attempted to alter some of the built-in Identity columns.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

    // Other modelBuilder stuff here

    // This line only required if using ASP.Net Identity:
    base.OnModelCreating(modelBuilder);

    // Force all string-based columns to non-unicode equivalent 
    // when no column type is explicitly set.
    foreach (var property in modelBuilder.Model.GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .Where(
               p => p.ClrType == typeof(string)    // Entity is a string
            && p.GetColumnType() == null           // No column type is set
            // Next line only required if using ASP.Net Identity:
            && !p.DeclaringEntityType.GetTableName().StartsWith("AspNet")
        ))
    {
        property.SetIsUnicode(false);
    }

}
Published On: October 29, 2020Categories: Entity Framework