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