Свободный NHibernate: Как отобразить отношения «многие ко многим» с дискриминатором - PullRequest
0 голосов
/ 01 марта 2012

У меня есть следующие таблицы и сущности, которые необходимо сопоставить в Fluent NHibernate.

Таблица:

CREATE TABLE workarea
(
  id uuid NOT NULL,
  name character varying(255) NOT NULL,
  CONSTRAINT pk_workarea PRIMARY KEY (id),
)

CREATE TABLE element
(
  id uuid NOT NULL,
  name character varying(255) NOT NULL,
  CONSTRAINT pk_element PRIMARY KEY (id),
)

CREATE TABLE attachment
(
  id uuid NOT NULL,
  filename character varying(255) NOT NULL,
  CONSTRAINT pk_attachment PRIMARY KEY (id),
)  

CREATE TABLE objectattachment
(
  id uuid NOT NULL,
  attachmentid uuid NOT NULL,
  attachmenttype string NOT NULL,
  objectid uuid NOT NULL,
  CONSTRAINT pk_objectattachment PRIMARY KEY (id),
  CONSTRAINT fk_oa_a FOREIGN KEY (attachmentid)
      REFERENCES attachment (id) MATCH SIMPLE
      ON UPDATE RESTRICT ON DELETE RESTRICT,
  CONSTRAINT fk_oa_at FOREIGN KEY (attachmenttypeid)
      REFERENCES attachmenttype (id) MATCH SIMPLE
      ON UPDATE RESTRICT ON DELETE RESTRICT
)

Идея этого дизайна базы данных заключается в следующем:

  • «Рабочая область» или «элемент» могут иметь несколько файлов «вложений», а файл «вложений» может указываться несколькими «рабочими областями» или «элементами».

  • «Рабочая область» или «элемент» могут относиться к одному и тому же файлу «вложения».

Таким образом, отношения между "вложениями" и "рабочими областями" или "элементами" хранятся в "objectattachment" таблица, в которой:

  • Поле «attachmentid» относится к идентификатору конкретного «attachment» s.

  • Поле «тип вложения» (дискриминатор) определяет, будет ли это отношение находится между "привязанностью" и "рабочей областью" или между "привязанностью" и "элемент" s.

  • Поле «objectid» относится к идентификатору конкретной «рабочей области» или «элемента» в зависимости от значения указанного выше поля «attachmenttype».

На основе структуры базы данных я определяю классы модели предметной области следующим образом:

public class WorkArea    
{
     private Guid _id = Guid.Empty;
     private string _name;
     public virtual Guid Id     
     {
          get { return _id ; }
          set { _id = value; }
     }
     public virtual string Name     
     {
          get { return _name ; }
          set { _name = value; }
     }
}

public class Element    
{
     private Guid _id = Guid.Empty;
     private string _name;
     public virtual Guid Id     
     {
          get { return _id ; }
          set { _id = value; }
     }
     public virtual string Name     
     {
          get { return _name ; }
          set { _name = value; }
     }
}

public class Attachment
{
     private Guid _id = Guid.Empty;
     private string _fileName;
     public virtual Guid Id     
     {
          get { return _id ; }
          set { _id = value; }
     }
     public virtual string FileName     
     {
          get { return _fileName; }
          set { _fileName= value; }
     }
}

public class WorkAreaAttachment : Attachment
{
     private WorkArea _workArea;
     public virtual WorkArea WorkArea 
     {
          get { return _workArea; }
          set { _workArea = value; }
     }     
}

public class ElementAttachment : Attachment
{
     private Element _element;
     public virtual Element Element
     {
          get { return _element; }
          set { _element = value; }
     }     
}

Теперь мой вопрос заключается в том, смогу ли я отобразить эти классы модели предметной области с помощью вышеуказанного дизайна базы данных. Если да, то как я могу это сделать? Если нет, то как изменить классы модели предметной области для поддержки сопоставления Fluent NHibernate с разработанной базой данных, поскольку я не хочу изменять текущий дизайн базы данных (т. Е. Создавать отдельные таблицы «вложений» для «рабочей области» и «элемента») .

С уважением, Quan

1 Ответ

0 голосов
/ 01 марта 2012
public class AttachmentLink
{
     private Attachment _attachment;
     public virtual Attachment Parent
     {
          get { return _attachment; }
          set { _attachment = value; }
     }

     private IHasAttachments _linkedTo;
     public virtual IHasAttachments LinkedTo
     {
          get { return _linkedTo; }
          set { _linkedTo = value; }
     }
}

// in AttachmentMap
HasMany(x => x.Links)
    .Table("objectattachment");

// map the component
sealed class AttachmentLinkMap : ComponentMap<AttachmentLink>
{
    public AttachmentLinkMap()
    {
        References(x => x.Attachment, "attachmentid");
        ReferencesAny(x => x.LinkedTo)
            .IdentityType<Guid>()
            .EntityIdentifierColumn("objectid")
            .EntityTypeColumn("attachmenttype")
            .AddMetaValue<WorkArea>(typeof(WorkArea).Name.ToLower())
            .AddMetaValue<Element>(typeof(Element).Name.ToLower())
            .Not.LazyLoad();  // to prevent false proxies
    }
}


// in ElementMap, and almost the same in WorkAreaMap
HasManyToMany(x => x.Attachments)
    .Where("attachmenttype='element'")

Примечание: вам не нужен столбец Id в таблице ссылок

...