Frage

Ich habe im Grunde eine Money Werttyp, der aus besteht aus Amount und Currency. Ich muss mehrere zuordnen Money Werte in eine Tabelle, die mehrere Felder für den Betrag hat, jedoch nur eine Währung. In Ordnung Wörter habe ich die Tabelle:

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

Dies muss einer Klasse mit 2 Geldwerten abgebildet werden (was logischerweise nie unterschiedliche Währungen haben kann):

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

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

(Beispiel ist etwas vereinfacht)

Das Tabellenschema kann nicht geändert werden. Ich freue mich, eine implementieren zu können IUserType, bei Bedarf, aber ich kann nicht herausfinden, wie ich auf die zugreifen soll Currency Spalte für beide Werte.

Wie kann ich das mit NhiberNate zuordnen?

War es hilfreich?

Lösung

Es ist nicht möglich.

Wenn Sie ein Geld erstellen, ist userType der Zweck des Typs, zwei Primitive zu einem neuen Einzeldatentyp zu kombinieren. Dieser Datentyp ist jetzt eine einzelne Atomeinheit. Da der Benutzertyp als Atomtyp angesehen wird, müssen beide Spalten für jeden zugeordneten Geldwert vorhanden sein. Die Regel, die Nhibernate durchsetzt, ist tatsächlich semantisch korrekt. Sie haben zwei Geldwerte. Daher müssen Sie zwei Währungen haben - sie können keine teilen, da ein einzelner Geldtyp eine Währung und einen Betrag hat und dies eine Atomdateneinheit ist, die nicht aufgeteilt oder geteilt werden kann.

Sie möchten manchmal Währung als Variable behandeln und daher eine eigene Spalte benötigen und zu anderen Zeiten als festgelegt, damit mehrere Benutzertypen alle eine Spalte teilen können. Selbst wenn dies gültig wäre, was nicht darauf basiert, wie ein Geld definiert wird, wie würde Nhibernate wissen, was Sie tun wollten, wann? Das System kann nicht einfach wissen, was Sie zu einem bestimmten Zeitpunkt wollen. Sie müssten jetzt auch zusätzliche Daten mit dem Geldtyp sparen, der angegeben hat, wie ein bestimmter Wert verwendet werden sollte.

Fazit können Ihre Spalten nicht als Benutzertyp zugeordnet werden. Wenn Sie das Schema nicht ändern können, können Sie dies nur tun, um alle drei Spalten als normale Primitive zuzuordnen und dann einen Geldtyp in Ihrem Anwendungscode zu konstruieren (und zu dekonstruieren).

Und für was endet? Ich bin wirklich überrascht, dass selbst jemand wie Fowler diesen Ansatz als eine Art "Best Practice" vorschlägt, ohne wirklich die tatsächlichen Details zu betrachten. Tatsache ist, dass die meisten Daten ein Satz sind, an dem die Währung für eine Reihe von einigen oft impliziten oder externen Faktoren wie Herkunftsland oder Land diktiert wird, in dem ein Unternehmen tätig ist usw. usw. usw.

Die Anlässe, bei denen Sie möglicherweise sogar Währung benötigen, haben Sie oft so viel anderes Gepäck, das aus mehreren Währungen wie aktuellen Wechselkursen usw. entsteht, dass die Währung als Teil und Paket eines Geldtyps nicht einmal so hilfreich ist. Es ist eine Bequemlichkeit, aber für Daten, die sehr unpraktisch zu arbeiten sind und nicht auf andere Weise hergestellt werden können. Die meiste Zeit ist die Währung festgelegt und kann normalerweise sogar abgeleitet werden. Ein Geldtyp in typischen Fällen kann also entweder dem, was Sie wirklich benötigen - nicht annähernd - eine Konvertierung, oder es handelt sich einfach um unnötige Informationen. Mit wenigen Ausnahmen wird der Geldtyp nur zu einer Dingleberry auf dem Arsch der Anwendung.

Bevor Sie viel Zeit damit verbringen, etwas für möglicherweise wenig oder keinen anderen Grund zu implementieren, als die Leute angefangen haben, dies als "bewährte Verfahren" zu bezeichnen, fragen Sie sich, ob Sie es jemals für irgendetwas verwenden müssen?

Andere Tipps

Es ist nicht möglich, weil es keinen Sinn macht, wenn Sie in Betracht ziehen lesen und Schreiben Entitäten.

Betrachten Sie den Fall, in dem Value1 ist USD 20 und value2 ist GBP 40. Wie würdest du es bestehen?

Was ist mit solchen Klassen?

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; }
}

Jetzt können Sie einen Benutzertyp für schreiben MoneyCollection.

Hinweis: Sie müssen sicherstellen, dass die MoneyCollection hat eine konstante Zahl oder zumindest eine maximale Anzahl von Werten, da Sie sie einer konstanten Anzahl von Spalten zuordnen müssen. Überprüfen Sie dies in der Klasse selbst.

Ich bin nur ein Neuling, der nur seit einigen Monaten etwas über und mit NhiberNate arbeite, aber ist es nicht möglich, einen komplexen UserType (iEnhancedUsertype) zu erstellen, der in mehrere Spalten schreibt, während eine Spalte überflüssig sein wird?

Schwer zu erklären, aber wenn Sie eine Eigenschaft in Ihrer Entität in der Währungsspalte zuordnen, die sich um Lese-/Schreibaktionen kümmert und Sie mehrmals innerhalb der komplexen UserType -Zuordnung und Einfügen auf dieselbe Spalte verweisen, um ein Einfügen auszuschalten und zu aktualisieren, so Readonly Spalte, würde das nicht funktionieren? Ich habe darüber nachgedacht, einen solchen Usertyp zu machen, um zu sehen, ob es funktioniert (da ich es noch nicht ausprobiert habe, habe ich keinen Beispiel -Code -ATM))

Ich weiß, es ist ein paar Jahre zu spät - aber ich habe eine Lösung.

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;
    }
}

Kartierung:

Map(Reveal.Member<Basket>("_subTotal")).Column("SubTotal");
Map(Reveal.Member<Basket>("_shipping")).Column("Shipping");
Map(Reveal.Member<Basket>("_currency")).Column("Currency");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top