2009-04-16 6 views
0

Tableau:NHibernate Component Mapping Courant - Chaîne DB valeur passée à une usine donne le type d'objet requis

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

Modèle:

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

C'est une grande simplification du domaine du problème.

La ligne Map(x => x.Tenor); ne fonctionnera évidemment pas, car vous ne pouvez pas implicitement convertir la colonne VARCHAR en un type ITenor. Existe-t-il un moyen de mapper pour utiliser automatiquement Factory pour obtenir l'ITenor requis pour la chaîne spécifiée dans la base de données et utiliser ToString() de la classe ITenor pour revenir à la base de données?

Si non, quel refondoring recommanderiez-vous pour rendre cela faisable? Merci beaucoup

Répondre

2

Une solution possible est de conserver la chaîne telle qu'elle est dans la base de données et de la mapper à une propriété TenorString. Puis ajoutez une autre propriété de type qui fait simplement la transformation entre la chaîne et la valeur typée:

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

TenorString est mis en correspondance normaly mais la propriété Tenor n'est pas mis en correspondance à tous:

Map(x => x.TenorString); 

Off Bien sûr, le Tenor obtenir La propriété peut renvoyer une valeur mise en cache réinitialisée lorsque TenorString est modifiée pour éviter l'appel d'usine à chaque fois.

+1

C'est probablement la méthode la plus simple. Vous pouvez également créer un type personnalisé en implémentant IUserType: http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/mapping.html#mapping-types-custom –

+0

Merci beaucoup Aleris et Stuart. Je vais plutôt implémenter IUserType car je ne veux pas pirater la classe Instrument, mais c'est une solution de contournement très simple. – Hendrik

Questions connexes