2010-03-15 2 views
4

Я создаю модель домена, где объекты часто (но не всегда) имеют член типа ActionLog.Карта NHibernate entity для нескольких таблиц на основе родителя

ActionLog - это простой класс, который позволяет проверять след действий, выполняемых на экземпляре. Каждое действие записывается как экземпляр ActionLogEntry.

ActionLog реализуется (приблизительно) следующим образом:

public class ActionLog 
{ 
    public IEnumerable<ActionLogEntry> Entries 
    { 
     get { return EntriesCollection; } 
    } 

    protected ICollection<ActionLogEntry> EntriesCollection { get; set; } 

    public void AddAction(string action) 
    { 
     // Append to entries collection. 
    } 
} 

То, что я хотел бы, чтобы повторно использовать этот класс среди моих субъектов и имеют записи на карту в разные таблицы, на основании которых класс они вошли против , Например:

public class Customer 
{ 
    public ActionLog Actions { get; protected set; } 
} 

public class Order 
{ 
    public ActionLog Actions { get; protected set; } 
} 

Эта конструкция подходит для меня в применении, однако я не могу видеть ясный способ отображения этого сценария к базе данных с NHibernate.

Обычно я использую Fluent NHibernate для своей конфигурации, но я счастлив принять ответы в более общем HBM xml.

+0

Есть ли какая-то конкретная причина, по которой вы хотите, чтобы каждый тип действий переходил на отдельную таблицу? –

+0

Это более естественная форма для реляционной структуры. Реально, у вас есть таблицы 'Customers' и' CustomerActionLogEntries'. Параллельно с этим вы имеете таблицы «Заказы» и «OrderActionLogEntries». В настоящее время мое решение состоит в том, чтобы иметь единственную таблицу ActionLogEntries и использовать таблицы объединения с отношениями «многие-ко-многим» в NHibernate. Это слишком нормализовано для моих вкусов, требуя объединения повсюду, чтобы получить какие-либо значимые данные. –

+0

Вы когда-нибудь получали разрешение на это? Я собираюсь опубликовать тот же вопрос. – Origin

ответ

3

У меня была такая же проблема и была о посте и тот же вопрос в надежде на ответ - но я нашел решение с помощью IRC NH канал на FreeNode.

В моем сценарии есть документ. У разных вещей будут документы - такие как отчеты, элементы и т. Д. Единственное отличие между Report.Documents и Item.Documents заключается в том, что документ имеет ссылку на его владельца и сопоставляется с другой таблицей.

Решение этой ситуации в основном выполняется через .Net. Хотя - я не думаю, что это решение было бы возможно с XML-сопоставлениями.

Класс документа:

Public Class Document 
    Public Overridable Property DocumentId As Integer 
    Public Overridable Property Directory As String 
    Public Overridable Property Name As String 
    Public Overridable Property Title As String 
    Public Overridable Property Revision As String 
    Public Overridable Property Description As String 
    Public Overridable Property Owner As String 
    Public Overridable Property UploadedBy As String 
    Public Overridable Property CreationDate As Date 
    Public Overridable Property UploadDate As Date 
    Public Overridable Property Size As Int64 
    Public Overridable Property Categories As String 
End Class 

Тогда мы наследуем от этого класса для каждого из наших дополнительных типов документов:

Public Class ReportDocument 
    Inherits Document 
    Public Overridable Property Report As Report 
End Class 

Public Class ItemDocument 
    Inherits Document 
    Public Overridable Property Item As Item 
End Class 

Вот где "магия" происходит. Мы собираемся создать общее сопоставление, которое требует, чтобы используемый объект наследовал класс Document. Таким образом, Fluent NHibernate все еще может найти все свойства объектов, которые наследуются от документа.

Public Class GenericDocumentMapping(Of T As Document) 
    Inherits ClassMap(Of T) 
    Public Sub New() 
     Id(Function(x) x.DocumentId) 
     Map(Function(x) x.Directory) 
     Map(Function(x) x.Name) 
     Map(Function(x) x.Title).Not.Nullable() 
     Map(Function(x) x.Revision) 
     Map(Function(x) x.Description) 
     Map(Function(x) x.Owner) 
     Map(Function(x) x.UploadedBy) 
     Map(Function(x) x.CreationDate).Not.Nullable() 
     Map(Function(x) x.UploadDate).Not.Nullable() 
     Map(Function(x) x.Size) 
     Map(Function(x) x.Categories) 
    End Sub 
End Class 

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

Public Class ReportDocumentMapping 
    Inherits GenericDocumentMapping(Of ReportDocument) 
    Public Sub New() 
     MyBase.New() 
     References(Function(x) x.Item).Column("ReportID") 
     Table("ReportDocuments") 
    End Sub 
End Class 

Public Class ItemDocumentMapping 
    Inherits GenericDocumentMapping(Of ItemDocument) 
    Public Sub New() 
     MyBase.New() 
     References(Function(x) x.Item).Column("ItemID") 
     Table("ItemDocuments") 
    End Sub 
End Class 

Я думаю, что этот метод уменьшает количество кода. Теперь, если вы хотите внести радикальные изменения в тип документа - вам нужно только изменить класс Document и класс GenericDocumentMapping.

В моей ситуации - я также просто привязываю документы к определенной таблице.Это делается так же, как и другие, - наследуйте от GenericDocumentMapping и укажите таблицу. Единственное различие заключается в том, что я не ссылаюсь на родительский объект.

Public Class DocumentMapping 
    Inherits GenericDocumentMapping(Of Document) 
    Public Sub New() 
     MyBase.New() 
     Table("Documents") 
    End Sub 
End Class 
+0

Этот ответ представляет разумный компромисс и довольно умный подход к проблеме. –

0

youu можно использовать присоединиться к карте это более чем таблица

Смежные вопросы