首先在实体框架模型中使用货币类型
本文关键字:货币 类型 模型 实体 框架 | 更新日期: 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"}