NHibernate 将实体映射到通用查找表

发布于 2024-11-18 02:27:08 字数 425 浏览 1 评论 0原文

我正在针对旧数据库构建一个应用程序,该数据库将查找值存储在通用表中(实际上它保存在四个不同的表中)。这意味着实体表存储查找值的“id”,元数据表保存“该值的描述”。

元数据表按如下方式细分:

  • TableInfo
  • ColumnInfo
  • BusinessInfo
  • LookupDescriptionInfo

要获取查找描述,您需要连接所有四个表并指定表名称、列名称和查找 ID。查找描述信息表包含两列——一列用于文本值,一列用于数值。

我希望为每个查找类型都有一个单独的类(例如,我的 Widget 类将根据 Widget.WidgetTypeId 值与“WidgetType”建立多对一关系。)实现此目的的一些策略是什么?该数据模型已被 1000 多个 RPG 程序使用,因此无法更改。

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 used by over 1000 RPG programs, so it can't be altered.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧时浪漫 2024-11-25 02:27:08

我遇到了与您几乎完全相同的问题,并发现以下可行的解决方案。

创建 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

创建基本 Lookup 类

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
}

创建继承的 LookupClass

public class ArmourLookup : Lookup{}

在业务对象上使用 ArmourLookup 类。

public class HeroArmour{
    //Usual properties etc....
    public virtual ArmourLookup Lookup {get; 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");
    }
}

现在,您可以轻松地为创建新类型的每个列重复子类映射。这里的问题是您无法更新或插入新的查找到视图中,因此您处于只读模式。

此方法使用列名作为鉴别器,因此不需要表名,但如果查找表中有重复的列名,您可以为每个表创建一个基本查找类,并在映射中指定过滤条件。


另一个潜在的解决方案可能是使用 T4 模板从查找表生成的枚举。尽管这也是一种只读方法。


您还可以将每个查找表映射为一个类,并使用鉴别器模式从 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...

如果列信息表中有重复的列名但 tableid 不同,您可以选择区分某些 XTable 类。

您还可以区分 ColumnType(数字或文本)并对 LookupDescription 类进行子类化,以对“Description”属性使用不同的列。

如果您可以提供您的表格结构和一些示例值,我可以为您进一步充实这些想法。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文