添加属性以在 Entity Framework Core 中配置小数精度

she*_*mus 5 c# entity-framework entity-framework-core

我的 EF 6 .Net Framework 应用程序具有以下属性:

[AttributeUsage(AttributeTargets.Property)]          
public sealed class DecimalPrecisionAttribute : Attribute
{              
    public DecimalPrecisionAttribute(Byte precision, Byte scale)
    {
        Precision = precision;
        Scale = scale;
    }

    public Byte Precision { get; set; }
    public Byte Scale { get; set; }
}

public class DecimalPrecisionAttributeConvention
    : PrimitivePropertyAttributeConfigurationConvention<DecimalPrecisionAttribute>
{
    public override void Apply(
        ConventionPrimitivePropertyConfiguration configuration,
        DecimalPrecisionAttribute attribute)
    {
        if (attribute.Precision < 1 || attribute.Precision > 38)
        {
            throw new InvalidOperationException("Precision must be between 1 and 38.");
        }

        if (attribute.Scale > attribute.Precision)
        {
            throw new InvalidOperationException(
                "Scale must be between 0 and the Precision value.");
        }

        configuration.HasPrecision(attribute.Precision, attribute.Scale);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的 DbContext 中:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
        base.OnModelCreating(modelBuilder);
    }
Run Code Online (Sandbox Code Playgroud)

这使我可以在我的 POCO 上设置属性的精度:

[DecimalPrecision(5,2)]
public Decimal WeirdNumber { get; set; }
Run Code Online (Sandbox Code Playgroud)

但是我无法弄清楚如何为 EF Core 执行此操作。

.Core 中是否有等价物?

我想出了以下几点:

public static class DecimalPrecisionAttributeConvention
{
    public static void ApplyToTable(IMutableEntityType table)
    {
        foreach (var col in table.GetProperties())
        {
            var attribute = col
                ?.PropertyInfo
                ?.GetCustomAttributes<DecimalPrecisionAttribute>()
                ?.FirstOrDefault();

            if (attribute == null)
            {
                continue;
            }

            if (attribute.Precision < 1 || attribute.Precision > 38)
            {
                throw new InvalidOperationException("Precision must be between 1 and 38.");
            }

            if (attribute.Scale > attribute.Precision)
            {
                throw new InvalidOperationException(
                    "Scale must be between 0 and the Precision value.");
            }

            col.Relational().ColumnType =
                $"decimal({attribute.Precision}, {attribute.Scale})";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并瘦我的模型创建:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        foreach (var table in modelBuilder.Model.GetEntityTypes())
        {
            DecimalPrecisionAttributeConvention.ApplyToTable(table);
        }
    }
Run Code Online (Sandbox Code Playgroud)

是实现这一目标的最佳方法吗?

小智 3

对于 EntityFrameworkCore,我使用此解决方案。在 DbContext 中,重写 OnModelCreating 方法:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // Set default precision to decimal property
            foreach (var property in modelBuilder.Model.GetEntityTypes()
                .SelectMany(t => t.GetProperties())
                .Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
            {
                property.SetColumnType("decimal(18, 2)");
            }
        }
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。