我基本上有一个 Money 价值类型,包括 AmountCurrency. 。我需要映射多个 Money 值进入表,该表具有多个字段的金额,但只有一种货币。从顺序的话来说,我有桌子:

Currency     Amount1    Amount2
===============================
USD          20.00      45.00

需要将其映射到具有2个货币价值的课程(从逻辑上讲永远不会有不同的货币):

class Record
{ 
    public Money Value1 { get; set; }
    public Money Value2 { get; set; }
}

struct Money 
{
    public decimal Amount { get; set; }
    public string Currency { get;set; }
} 

(例如,简化了一些)

表模式无法更改。我很高兴实施 IUserType, ,如果需要,但是我不知道如何访问 Currency 两个值的列。

如何使用NHIBERNATE映射此图?

有帮助吗?

解决方案

这不可能。

如果您创建了Money USERTYPE,则该类型的目的是将两个原语组合到新的单个数据类型中。该数据类型现在是单个原子单元。因为使用使用者被认为是原子类型,必须为每个货币价值映射两个列。 NHIBERNATE的规则实际上在语义上是正确的。您有两个金钱价值。因此,您必须有两种货币 - 他们不能共享一种货币,因为单个货币类型具有货币和金额,这是一个原子数据单位,它不能分开或共享。

您有时希望将货币视为可变,因此需要自己的列,而其他时间则为固定,以便多种使用类型都可以共享一列。即使那是有效的,它不是基于金钱的定义方式,nhibernate如何知道您想做什么?该系统不仅在任何给定时间都知道您想要什么。现在,您还需要使用指定任何给定值的使用方式的货币类型保存其他数据。

底线,您的列无法映射为使用类型。如果您无法更改模式,那么您可以做到这一点的唯一方法是将所有三列映射为普通原始图,然后在您的应用程序代码中构造(和解构)金钱类型。

而什么目的?我真的很惊讶,即使像Fowler这样的人都建议这种方法是某种“最佳实践”,而没有真正考虑实际细节。事实是大多数数据是一套集合,其中某些经常隐含的或外部因素(例如原籍国或企业经营等的国家 /地区)为行规定了货币。

您实际上可能需要货币的情况下,您通常会有很多其他行李,这些行李是由当前汇率等多种货币产生的,以货币为一部分和货币类型的包裹都不是那么有用。这是一个方便的,但是对于数据非常不便,与众不同。大多数时间货币都是固定的,通常甚至可以推断。因此,在典型情况下,金钱类型要么不能接近您真正需要的东西 - 转换,要么只是不必要的信息。除少数例外,钱类型只是应用程序屁股上的丁香。

在您花费大量时间尝试以某种方式称其为“最佳实践”以外的原因可能很少或没有其他原因之前,请问自己您是否曾经需要将其用于任何东西?

其他提示

这是不可能的,因为当您考虑时没有意义 读写 实体。

考虑Value1的情况 USD 20 和value2是 GBP 40. 。您将如何坚持下去?

那样改变您的课程怎么样?

class Record
{ 
    public MoneyCollection Money { get; set; }
}

class MoneyCollection
{
    public MoneyCollection(string currency, params decimal[] amount1) { /*...*/ }
    public decimal[] Amount { get; private set; }
    public string Currency { get; private set; }
    public Money[] Money
    {
      get
      {
        return Amount.Select(x => new Money(Currency, x)).ToArray();
      }
    }
} 

class Money 
{
    public Money(decimal amount, string currency ) { /* ... */ }
    public decimal Amount { get; private set; }
    public string Currency { get; private set; }
}

现在您可以编写一个用户类型 MoneyCollection.

注意:您需要确保 MoneyCollection 具有恒定数字,或者至少具有最大值的值,因为您需要将其映射到恒定数量的列数。在课堂本身中检查一下。

我只是一个新手只学习并与Nhibernate一起工作了几个月,但是不可能制作复杂的使用使用类型(Ienhancedusertype),将其写入多个列,而一列会多余?

难以解释,但是如果您将实体中的属性映射到货币列,该列表负责读/写操作,并且您在复杂的USERTYPE映射中多次参考同一列,并关闭插入和更新,从而使其成为Readonly专栏,那不起作用吗?我一直在考虑尝试制作这样的使用类型以查看它是否有效(因为我还没有尝试过,所以我没有任何示例代码atm)

我知道迟到了几年 - 但是我有一个解决方案。

private decimal _subTotal;
private decimal _shipping;
private CurrencyIsoCode _currency;

public virtual Money SubTotal
{
    get { return new Money(_subTotal, _currency); }
    set
    {
        _subTotal = value.Amount;
        _currency = value.CurrencyCode;
    }
}

public virtual Money Shipping
{
    get { return new Money(_shipping, _currency); }
    set
    {
        _shipping = value.Amount;
        _currency = value.CurrencyCode;
    }
}

映射:

Map(Reveal.Member<Basket>("_subTotal")).Column("SubTotal");
Map(Reveal.Member<Basket>("_shipping")).Column("Shipping");
Map(Reveal.Member<Basket>("_currency")).Column("Currency");
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top