简体   繁体   English

NHibernate map 实体到通用查找表

[英]NHibernate map entity to generic lookup table

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.我正在针对将查找值存储在通用表中的遗留数据库构建应用程序(实际上它保存在四个不同的表中。)这意味着实体表存储查找值的“id”,元数据表保存“描述”这个值。

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.要获取查找描述,您需要连接所有四个表并指定表名、列名和查找 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 (eg, 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?我想为每种查找类型有一个单独的 class(例如,我的 Widget class 将与基于 Widget.WidgetTypeId 值的“WidgetType”建立多对一关系。)有哪些策略可以实现这一点? The data model is used by over 1000 RPG programs, so it can't be altered.数据 model 被 1000 多个 RPG 程序使用,因此无法更改。

I have had almost exactly the same problem as you and have found the following solutions viable.我遇到了与您几乎完全相同的问题,并发现以下解决方案是可行的。

Create SQL View创建 SQL 查看

-- 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创建基本查找 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创建继承的 LookupClass

public class ArmourLookup : Lookup{}

Use the ArmourLookup class on your business objects.对您的业务对象使用 ArmourLookup class。

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.此方法使用列名作为鉴别器,因此无需表名,但如果您的查找表中有重复的列名,您可以为每个表创建基本查找 class 并在映射中指定过滤条件。


Another potential solution could be to use Enums generated by T4 templates from the lookup tables.另一种可能的解决方案是使用由查找表中的 T4 模板生成的枚举。 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.您还可以将每个查找表 map 作为 class 并使用鉴别器模式从 ColumnInfo 表中获取不同的类型。

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.如果您在列信息表中有重复的列名但 tableid 不同,您可以再次选择区分某些 XTable 类。

You could also discriminate on the ColumnType (numeric or text) and subclass the LookupDescription class to use different columns for the "Description" property.您还可以区分 ColumnType(数字或文本)并将 LookupDescription class 子类化为“描述”属性使用不同的列。

If you could provide your table structure and some sample values I could flesh these ideas out more for you.如果您可以提供您的表格结构和一些示例值,我可以为您进一步充实这些想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM