英文:
Can EF Core use MetadataType for migrations?
问题
EF Core 在创建数据库迁移时是否能够尊重 MetadataType
注解,比如 MaxLength 等?
我创建了一个人员类,并用 MetadataType
进行了装饰,但在添加数据库迁移时,这些注解似乎没有被考虑进去。
英文:
Is there a way to get EF Core to honour MetadataType
annotations for MaxLength etc when creating DB migrations?
I've created a person class and decorated it with MetadataType
but the annotations aren't considered when I add a DB migration.
答案1
得分: 1
以下是翻译的内容:
"Meanwhile, in case you are using EF Core 7.0 or later, you can utilize the Model building conventions and implement it yourself."
"同时,如果您正在使用EF Core 7.0或更高版本,您可以利用模型构建约定,并自己实现它。"
"First method is just for convenience, the actual work is inside ProcessPropertyAdded
switch. I've added support for 3 attributes, other can be added if needed in a similar fashion."
"第一个方法只是为了方便,实际工作在ProcessPropertyAdded
开关内。我已经为3个属性添加了支持,如果需要的话,可以以类似的方式添加其他属性。"
"With this code in place, all you need is to override ConfigureConventions
in your derived DbContext
class and include AddMetadaTypeAttributeSupport
call, e.g."
"有了这段代码,您只需要在派生的DbContext
类中重写ConfigureConventions
,并包括AddMetadaTypeAttributeSupport
调用,例如:"
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
base.ConfigureConventions(configurationBuilder);
configurationBuilder.AddMetadaTypeAttributeSupport();
}
英文:
These are not considered at all, not only during the migration. They (EF Core team) do not find a value for implementing such functionality given the multiple alternative options they provide - entity type configuration classes (close to MetadataType
classes, but with fluent API), OnModelCreating
, custom model conventions (ConfigureConventions
) etc.
Actually as you have found later, there is an open issue Conventions should honor [MetadataType] #14544 in EF Core issue tracker, but as of time of writing (EF Core 7.0) it's not considered to be addressed, which kind of proves my initial thoughts.
Meanwhile, in case you are using EF Core 7.0 or later, you can utilize the Model building conventions and implement it yourself.
Following is a sample implementation:
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
namespace Microsoft.EntityFrameworkCore
{
public static class ModelConfigurationBuilderExtensions
{
public static ModelConfigurationBuilder AddMetadaTypeAttributeSupport(this ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Add(sp => new MetadataTypeAttrubuteConvention());
return configurationBuilder;
}
}
}
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
{
public class MetadataTypeAttrubuteConvention : IPropertyAddedConvention
{
public void ProcessPropertyAdded(IConventionPropertyBuilder propertyBuilder, IConventionContext<IConventionPropertyBuilder> context)
{
var property = propertyBuilder.Metadata;
foreach (var metaProp in property.DeclaringEntityType.ClrType
.GetCustomAttributes<MetadataTypeAttribute>(true)
.SelectMany(metaType => metaType.MetadataClassType.GetProperties())
.Where(metaProp => metaProp.Name == property.Name
&& metaProp.PropertyType.IsAssignableFrom(property.ClrType)))
{
foreach (var metaAttr in metaProp.GetCustomAttributes(true))
{
switch (metaAttr)
{
case RequiredAttribute dataAttr:
propertyBuilder.IsRequired(true, fromDataAnnotation: true);
break;
case MaxLengthAttribute dataAttr:
if (dataAttr.Length > 0)
propertyBuilder.HasMaxLength(dataAttr.Length, fromDataAnnotation: true);
break;
case PrecisionAttribute dataAttr:
propertyBuilder.HasPrecision(dataAttr.Precision, fromDataAnnotation: true);
if (dataAttr.Scale.HasValue)
propertyBuilder.HasScale(dataAttr.Scale, fromDataAnnotation: true);
break;
}
}
}
}
}
}
First method is just for convenience, the actual work is inside ProcessPropertyAdded
switch. I've added support for 3 attributes, other can be added if needed in a similar fashion.
With this code in place, all you need is to override ConfigureConventions
in your derived DbContext
class and include AddMetadaTypeAttributeSupport
call, e.g.
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
base.ConfigureConventions(configurationBuilder);
configurationBuilder.AddMetadaTypeAttributeSupport();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论