NHibernate отображает сущность в общую таблицу поиска - PullRequest
3 голосов
/ 01 июля 2011

Я создаю приложение для устаревшей базы данных, в которой значения поиска хранятся в общей таблице (фактически она хранится в четырех разных таблицах). Это означает, что таблицы сущностей хранят «id» значения поиска и таблицы метаданных.удерживайте «описание» этого значения.

Таблицы метаданных разбиты следующим образом:

  • TableInfo
  • ColumnInfo
  • BusinessInfo
  • LookupDescriptionInfo

Чтобы получить описание поиска, вы объединяете все четыре таблицы и задаете имя таблицы, имя столбца и идентификатор поиска.Информационная таблица описания поиска содержит два столбца - один для текстовых значений и один для числовых значений.

Я хотел бы иметь отдельный класс для каждого типа поиска (например, мой класс Widget будет иметь многоотношения «один к одному» с «WidgetType» на основе значения Widget.WidgetTypeId.) Каковы некоторые стратегии для достижения этой цели?Модель данных используется более 1000 RPG-программ, поэтому ее нельзя изменить.

1 Ответ

5 голосов
/ 01 июля 2011

У меня была почти та же проблема, что и у вас, и я нашел следующие решения жизнеспособными.

Создание представления 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

Создать базовый класс поиска

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

Теперь вы можете с легкостью повторять отображение подклассов для каждого столбца, в котором вы создаете новые типы. Проблема в том, что вы не можете обновить или вставить новые поиски в представление, поэтому вы находитесь в режиме только для чтения.

Этот метод использует имя столбца в качестве дискриминатора, поэтому не использует имя таблицы, но если в вашей таблице поиска есть повторяющиеся имена столбцов, вы можете создать базовый класс поиска для каждой таблицы и указать условие фильтра в отображении.


Другим потенциальным решением может быть использование Enums, сгенерированных шаблонами 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...

Опять же, при желании вы можете решить выделить некоторые классы XTable, если у вас есть повторяющиеся имена столбцов в информационной таблице столбцов, но разные идентификаторы таблиц.

Вы также можете различать ColumnType (числовой или текстовый) и создавать подкласс класса LookupDescription, чтобы использовать разные столбцы для свойства «Description».

Если бы вы могли предоставить структуру вашей таблицы и некоторые примеры значений, я мог бы конкретизировать эти идеи для вас.

...