将NHibernate实体映射到基于父级的多个表

时间:2010-03-15 16:59:21

标签: nhibernate fluent-nhibernate

我正在创建一个域模型,其中实体经常(但不总是)拥有ActionLog类型的成员。

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的答案。

2 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,并且关于帖子同样的问题希望得到答案 - 但我在FreeNode的NH IRC频道的帮助下找到了解决方案。

我的方案有一个文档。各种各样的东西都有文档 - 比如Reports,Items等.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

然后我们从这个类继承我们的每个其他Document类型:

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仍然可以在继承Document的对象上找到所有属性。

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

答案 1 :(得分:0)

您可以使用联接将其映射到多个表