2009-04-16 3 views
0

Tabelle:Fluent NHibernate Component Mapping - String DB Value zu einer Fabrik übergeben ergibt den gewünschten Objekttyp

CREATE TABLE Instrument 
( Id    INT IDENTITY 
, Name   VARCHAR(50) 
, Tenor   VARCHAR(10) 
//... 

Modell:

interface ITenor 
    { 
     int Length { get; } 
     string ToString(); 
    } 

    class DayTenor : ITenor 
    { 
     public int Length 
     { 
      get { return 1; } 
     } 

     public override string ToString() 
     { 
      return "DAY"; 
     } 
    } 

    class MonthTenor : ITenor 
    { 
     public int Length 
     { 
      get { return 30; } 
     } 

     public override string ToString() 
     { 
      return "MONTH"; 
     } 
    } 

    class TenorFactory 
    { 
     ITenor GetTenor(string tenorString) 
     { 
      switch (tenorString) 
      { 
       case "DAY": 
        return new DayTenor(); 
        break; 
       case "MONTH": 
        return new MonthTenor(); 
        break; 
       default: 
        throw new NotImplementedException(string.Format("Tenor {0} is not implemented", tenorString)); 
      } 
     } 
    } 

    class Instrument 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public ITenor Tenor { get; set; } 
    } 

    class InstrumentMap : ClassMap<Instrument> 
    { 
     public InstrumentMap() 
     { 
      WithTable("Instrument"); 
      Id(x => x.Id); 
      Map(x => x.Name); 
      Map(x => x.Tenor); 
     } 
    } 

Dies ist eine große Vereinfachung der Problemdomäne.

Die Zeile Map(x => x.Tenor); funktioniert eindeutig nicht, da Sie die VARCHAR-Spalte nicht implizit in einen ITenor-Typ konvertieren können. Gibt es einen Weg, den ich zuordnen kann, um die Factory automatisch zu verwenden, um das ITenor zu erhalten, das für die angegebene Zeichenfolge in der Datenbank benötigt wird, und die ToString() aus der ITenor-Klasse zu verwenden, um zu der DB zurückzukehren?

Wenn nicht, welche Refactoring würden Sie empfehlen, dies machbar zu machen? Vielen Dank

Antwort

2

Eine mögliche Lösung besteht darin, die Zeichenfolge unverändert in der Datenbank zu belassen und sie einer TenorString-Eigenschaft zuzuordnen. Dann fügen Sie eine weitere typisierte Eigenschaft, die einfach funktioniert die Transformation zwischen der Saite und dem eingegebenen Wert:

class Instrument 
{ 
    public string TenorString { get; set; } 
    public ITenor Tenor { 
     get { return GetTenor(this.TenorString); } 
     set { TenorString = value.ToString() }; 
    } 
} 

TenorString abgebildet normaly aber Tenor Eigenschaft ist überhaupt nicht abgebildet:

Map(x => x.TenorString); 

Natürlich ist auch der Tenor erhalten Diese Eigenschaft kann einen zwischengespeicherten Wert zurückgeben, der zurückgesetzt wird, wenn sich TenorString ändert, um den Factory-Aufruf jedes Mal zu vermeiden.

+1

Dies ist wahrscheinlich die einfachste Methode. Sie könnten auch einen benutzerdefinierten Typ erstellen, indem Sie IUserType implementieren: http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/mapping.html#mapping-types-custom –

+0

Vielen Dank Aleris und Stuart. Ich werde eher IUserType implementieren, da ich die Instrument-Klasse nicht hacken möchte, aber es ist eine sehr einfache Problemumgehung. – Hendrik