开发者

NHibernate map entity to generic lookup table

开发者 https://www.devze.com 2023-03-16 14:37 出处:网络
I\'m building an application against a legacy database that stores lookup values in a generic table (actually it\'s held in four different tables.) This means that the entity tables store the \"id\" o

I'm building an application against a legacy database that stores lookup values in a generic table (actually it's held in four different tables.) This means that the entity tables store the "id" of the lookup value and the metadata tables hold the "description" of this value.

The metadata tables are broken down like this:

  • TableInfo
  • ColumnInfo
  • BusinessInfo
  • LookupDescriptionInfo

To get the lookup description, you join all four tables and specify the table name, column name, and lookup id. The lookup description info table contains two columns---one for text values and one for numeric values.

I'd like to have a separate class for each lookup type (e.g., my Widget class would have a many-to-one relationship with "WidgetType" based on the Widget.WidgetTypeId value.) What are some strategies for accomplishing this? The data model is开发者_C百科 used by over 1000 RPG programs, so it can't be altered.


I have had almost exactly the same problem as you and have found the following solutions viable.

Create SQL View

-- I'm guessing at the table join structure here
create view LookupView
as
select t.TableName, 
   ci.ColumnName,
   bi.Id, --This ID column needs to be the one used as the FK from other tables
   bi.*, --Or whatever columns you need
   coalesce(di.TextDescription, di.NumericDescription) as Description
from TableInfo t
join ColumnInfo ci on t.Id=ci.TableId
join BusinessInfo bi on bi.Id=ci.BusinessId
join LookupDescriptionInfo di on di.id=ci.id

Create base Lookup Class

public class Lookup {
    public virtual string Tablename {get; set;}
    public virtual string ColumnName {get; set;}
    public virtual string Description {get; set;}
    public virtual int Id {get; set;}
    //Other BusinessInfo properties
}

Create a inherited LookupClass

public class ArmourLookup : Lookup{}

Use the ArmourLookup class on your business objects.

public class HeroArmour{
    //Usual properties etc....
    public virtual ArmourLookup Lookup {get; set;}
}

Create a subclass discriminated mapping set

public class LookupMap : ClassMap<Lookup> {
    public LookupMap(){
        Id(x=>x.Id).GeneratedBy.Assigned(); //Needs to be a unique ID
        Map(x=>x.Tablename);
        Map(x=>x.ColumnName);
        Map(x=>x.Description);
        //Business Info property mappings here
        Table("LookupView")
        DiscriminateSubClassesOnColumn<string>("ColumnName");
        ReadOnly();
    }
}

public class ArmourLookupMap : SubClassMap<ArmourLookup> {
    public ArmourLookupMap (){
        DiscriminatorValue("ArmourColumn");
    }
}

Now you can repeat the subclass mapping for every column you have creating new types with ease. The issue here is that you cannot update or insert new lookups into the View so you are in a read-only mode.

This method uses the column name as the discriminator so does away with the table name but if you have duplicate column names in your lookup table you could create a base lookup class for every table and specify a filter condition in the mapping.


Another potential solution could be to use Enums generated by T4 templates from the lookup tables. Although this also is a read only approach.


You could also map out each lookup table as a class and use the discriminator pattern to get different types from the ColumnInfo table.

public class TableInfo {
     public virtual int Id {get; set;} 
     public virtual string Tablename {get; set;}
     public IList<ColumnInfo> Columns {get; set;}
}

public class ColumnInfo {
   public virtual int Id {get; set;}
   public virtual TableInfo TableInfo {get; set;}
   public virtual BusinessInfo BusinessInfo {get; set;}
   public virtual LookupDescriptionInfo LookupDescriptionInfo {get; set;}
   //Other properties
}

public class ArmourInfoColumn : ColumnInfo {
    //In the mapping you would discriminate on the columnname column.
}

etc...

Again optionally you can decide to discriminate out some XTable classes if you have duplicate column names in the column info table but different tableid's.

You could also discriminate on the ColumnType (numeric or text) and subclass the LookupDescription class to use different columns for the "Description" property.

If you could provide your table structure and some sample values I could flesh these ideas out more for you.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号