質問

私は基本的に持っています Money で構成される値タイプ AmountCurrency. 。複数のマッピングする必要があります Money テーブルへの値。複数のフィールドが金額を備えていますが、1つの通貨のみがあります。言葉で言えば、私はテーブルを持っています:

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を作成する場合、タイプの目的は、2つのプリミティブを新しい単一のデータ型に結合することです。そのデータ型は、単一の原子単位になりました。 UserTypeは原子タイプと見なされるため、マッピングされた各列には両方の列が存在する必要があります。 nhibernateが強制しているルールは、実際には意味的に正しいです。 2つのお金の価値があります。したがって、2つの通貨が必要です - 単一のお金の種類に通貨と金額があり、それが1つの原子データユニットであるため、1つを共有できません。これは分割または共有できません。

通貨を変数として扱うことがあり、したがって独自の列を必要とすることがあり、他の時には、複数のユーザータイプがすべて列を共有できるように固定されている場合があります。たとえそれが有効であっても、お金の定義方法に基づいていない場合、Nhibernateはどのようにあなたが何をしたいかをどのように知るのでしょうか?システムは、いつでも必要なものを知ることはできません。また、特定の値がどのように使用されるかを指定したマネータイプを使用して追加のデータを保存する必要があります。

結論として、列はusertypeとしてマッピングすることはできません。スキーマを変更できない場合、これを行うことができる唯一の方法は、3つの列すべてを通常のプリミティブとしてマッピングし、アプリケーションコードでお金の種類を構築(および解体する)ことです。

そして、何のために?ファウラーのような人でさえ、実際の詳細を実際に考慮せずに、ある種の「ベストプラクティス」としてこのアプローチを提案することに本当に驚いています。事実は、ほとんどのデータは、ビジネスが運営されている出身国や国など、しばしば暗黙的または外部的な要因によって通貨が行われるセットです。

実際に通貨を必要とする可能性のある機会は、多くの場合、現在の為替レートなどの複数の通貨から生じる他の多くの荷物を持っているため、通貨とお金の種類の区画を持つことはそれほど役に立ちません。それは便利ですが、データのために作業するのが非常に不便で、そうでなければ作ることができません。ほとんどの時間通貨は固定されており、通常は推測することさえできます。したがって、典型的なケースのお金の種類は、あなたが本当に必要なものに近づくことはできません - それは単に不要な情報です。いくつかの例外を除いて、マネータイプは、アプリケーションのお尻の単なるディングルベリーになります。

何らかの形で人々がこれを「ベストプラクティス」と呼び始めた以外に、おそらくほとんどまたはまったく理由で何かを実装しようとして多くの時間を費やす前に、それを何かのために使用する必要さえありますか?

他のヒント

あなたが考えるときそれは意味をなさないのでそれは不可能です 読み書き エンティティ。

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について学んで仕事をしている初心者ですが、複数の列に書き込む複雑なusertype(ienhancedusertype)を作成することはできませんが、1つの列は冗長ですか?

説明が困難ですが、読み取り/書き込みアクションを処理する通貨列にエンティティ内のプロパティをマップし、複雑なUserTypeマッピング内で同じ列を複数回参照し、挿入と更新をオフにする場合、 readonly列、それはうまくいきませんか?私は、このようなusertypeを作ってそれが機能するかどうかを確認しようとしていました(まだ試していないので、コード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