由于Entity Framework使用nvarchar(max)
作为字符串的默认值,我想将其他内容设置为默认值。
在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)";
}
答案 0 :(得分:5)
有几个属性间接影响string
属性的列类型 - MaxLength
(例如varchar(256)
vs varchar(MAX)
,IsUnicode
(例如{{1} } {vs nvarchar
)和varchar
(例如IsFixedLength
vs char
)。
当前的模型API不一致。第一个可以通过GetMaxLength
和SetMaxLength
访问,第二个可以通过IsUnicode
和IsUnicode
访问,第三个没有公共模型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;