首先在实体框架模型中使用货币类型

本文关键字:货币 类型 模型 实体 框架 | 更新日期: 2023-09-27 17:59:25

我创建了一个表,该表有一个名为Amount的列,并将其设置为Decimal。我找不到哪里可以将其设置为货币或小额货币,当我尝试设置0.2这样的值时,它会四舍五入到0…

如何使用实体框架来使用资金?

谢谢!

首先在实体框架模型中使用货币类型

我的回复是关于E.F.6.0在处理了类似的问题并使用SQL事件探查器进行检查后:实体框架将Decimal变量类型转换为SQL中的Decimal(18,2)。

如果你想省钱类型,我建议使用数据注释并添加

public class Account
{
    public int AccountId { get; set; }                
    [Column(TypeName="money")]
    public decimal Amount { get; set; }
}

或者如果您使用Fluent API

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Account>()
                .Property(i => i.Amount)
                .HasColumnType("money");
}
  • 货币类型将转换为(19,4)

Entity Framework令人讨厌的一点是,它在SQL中将Decimal变量类型转换为Decimal(18,0)。

逗号后面的数字是数字上允许的小数位数。所以Decimal(18,0)在保存时会去掉小数点后的数字。

转到SQL Server Management stuido,找到您的数据库,右键单击表并选择"设计"。然后从列表中选择列,只需在框中键入即可将数据类型更改为Decimal(18,2)。然后将更改保存到表中。然后,它会将数字保存到西方货币交易中常用的小数点后两位。如果您需要更多的小数位数,只需相应地增加括号内的第二个数字。

我从来没有找到一个设置可以更改EF默认值,从而生成Decimal(18,2)。但后来我再也没有看:在DB中更改已经足够容易了。但如果有人知道其中一个,我会很好奇它是如何做到的。

编辑:此答案中包含更多信息,包括配置修复:EF Code First 中的小数精度和小数位数

所以我认为您的问题可能是针对代码优先的方法。此外,我不确定您使用的是哪种版本的SQL,我下面的答案仅适用于SQL Server。。但对于Oracle或MySQL,基本上都会采用相同的方式。

型号优先:

使用SQL Server,您只需为字段选择"money"或"smallmoney",具体取决于您需要表示的值的大小。

代码优先:

我需要表达一种高达9999.99 的货币类型

在可视化EDMX编辑器中,您将选择标量属性,转到"属性",然后将其设置为"类型=小数",然后设置"面"为"精度=6比例=2"。您可以使用"数据注释"来确保显示字段&投入作为货币。

这类似于EF Code First中的Decimal精度和小数位数.我首先使用EF 6.1和代码,由于某种原因,它默认情况下将smallmoney定义为精度2,尽管它是/应该是4。您需要添加一些Fluent代码来修复此问题。我使用类似的东西

public static void OnModelCreating(DbModelBuilder modelBuilder)
{
        modelBuilder.Entity<MYCLASSNAME>().Property(x => x.MYPROPNAME).HasPrecision(5+4, 4);
}

第一个货币类

public class Money
{
    public decimal Amount { get; set; }
    public string Currency { get; set; }
    public Money()
    {
    }

    public Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
}

货币价值转换器

public class MoneyValueConverter : ValueConverter<Money, string>
{
    private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = false
    };
    public MoneyValueConverter() : base(
        v => ConvertToString(v),
        v => ConvertToMoney(v))
    {
    }
    private static string ConvertToString(Money value)
    {
        // Convert the Money value to a JSON string representation
        // that can be stored in the database
        return JsonSerializer.Serialize(value, _jsonOptions);
    }
private static Money ConvertToMoney(string value)
{
    // Convert the JSON string value retrieved from the database
    // back to the Money object
    return JsonSerializer.Deserialize<Money>(value, new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    });
}

ModelBuilderExtensions

public static class ModelBuilderExtensions
{
    public static void ApplyMoneyValueConverter(this ModelBuilder modelBuilder)
    {
        var entityTypeList = modelBuilder.Model.GetEntityTypes().ToList();
        foreach (var entityType in entityTypeList)
        {
            var properties = entityType.ClrType.GetProperties()
                .Where(p => p.PropertyType == typeof(Money));
            foreach (var property in properties)
            {
                var entityBuilder = modelBuilder.Entity(entityType.ClrType);
                var propertyBuilder = entityBuilder.Property(property.PropertyType, property.Name);
                propertyBuilder.HasConversion(new MoneyValueConverter())
                               .HasColumnType("jsonb");
            }
        }
    }
}

然后在您的DbContext:中

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

在您的实体中,您可以拥有这样的属性:

public Money HourlyRate {get; set;}

在您的database中,有一个名为HourlyRate的字段具有jsonb

例如{"amount": 30.00, "currency": "EUR"}