EF Core 2.1.0设置默认字符串长度和列类型

时间:2018-06-13 15:14:42

标签: c# entity-framework entity-framework-core

由于Entity Framework使用nvarchar(max)作为字符串的默认值,我想将其他内容设置为默认值。

https://dba.stackexchange.com/questions/48408/ef-code-first-uses-nvarcharmax-for-all-strings-will-this-hurt-query-performan

在Entity Framework 6.1.3中,我可以像这样修改OnModelCreating(DbModelBuilder modelBuilder)

modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
modelBuilder.Properties<DateTime>().Configure(c => c.HasPrecision(0));

modelBuilder.Properties<string>()
    .Configure(s => s.HasMaxLength(256).HasColumnType("nvarchar"));

如果我随后修改了带有数据注释的属性,则EF使用这些值,如下所示:

[MaxLength(128)]
public string Name { get; set; }

[Column(TypeName = "nvarchar(MAX)")]
[MaxLength]
public string Comment { get; set; }

但是使用Microsoft.EntityFrameworkCore.SqlServer 2.1.0我不能这样做,我也不能使用Conventions

我可以像这样解决datetime但是如果我尝试对字符串执行相同的操作,那么如果我使用数据注释,则迁移会显示type: "nvarchar(256)", maxLength: 128。我该如何解决这个问题?

foreach (var property in modelBuilder.Model.GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .Where(p => p.ClrType == typeof(DateTime)))
{
    property.Relational().ColumnType = "datetime2(0)";
}

1 个答案:

答案 0 :(得分:5)

有几个属性间接影响string属性的列类型 - MaxLength(例如varchar(256) vs varchar(MAX)IsUnicode(例如{{1} } {vs nvarchar)和varchar(例如IsFixedLength vs char)。

当前的模型API不一致。第一个可以通过GetMaxLengthSetMaxLength访问,第二个可以通过IsUnicodeIsUnicode访问,第三个没有公共模型API(只有流畅的API)。

所以设置你可以使用的varchar

MaxLength

这不完全正确,因为在这种情况下foreach (var property in modelBuilder.Model.GetEntityTypes() .SelectMany(t => t.GetProperties()) .Where(p => p.ClrType == typeof(string))) { if (property.GetMaxLength() == null) property.SetMaxLength(256); } 具有双重含义 - 未指定和null

正确的方法需要使用EF Core内部API,它提供了更多的配置方法,特别是允许您将ConfigurationSource枚举值与属性值一起传递。 MAX枚举值定义配置的优先级 - ConfigurationSource最低,Convention,最后DataAnnotation最高。整个想法是优先级较低的配置不会覆盖已由较高优先级设置的配置。所有公共流利的API都使用Explicit,而在我们的情况下,Explcit非常适合(因为我们模拟了传统的默认值)。

因此,如果您接受警告“此API支持实体框架核心基础结构,并且不打算直接在您的代码中使用。此API可能会在将来的版本中更改或删除。”,添加

Convention

并使用

using Microsoft.EntityFrameworkCore.Metadata.Internal;