添加属性以在Entity Framework Core中配置十进制精度

时间:2017-10-14 20:30:01

标签: 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);
    }
}

然后在我的DbContext中:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
        base.OnModelCreating(modelBuilder);
    }

这允许我在我的POCO上设置属性的精度:

[DecimalPrecision(5,2)]
public Decimal WeirdNumber { get; set; }

但是我无法解决如何为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})";
        }
    }
}

瘦我的模特创造:

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

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

1 个答案:

答案 0 :(得分:0)

对于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)");
            }
        }

希望这会有所帮助。