【问题标题】:Map NHibernate entity to multiple tables based on parent根据父级将 NHibernate 实体映射到多个表
【发布时间】:2010-03-15 16:59:20
【问题描述】:

我正在创建一个域模型,其中实体通常(但不总是)具有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 中的答案。

【问题讨论】:

  • 您是否有特殊原因希望每种类型的操作转到单独的表?
  • 它更适合关系结构。相对而言,您有 CustomersCustomerActionLogEntries 表。与此并行的是OrdersOrderActionLogEntries 表。目前我的解决方案是拥有一个ActionLogEntries 表并在NHibernate 中使用具有多对多关系的连接表。这对我的口味来说有点太规范化了,需要到处加入才能获得任何有意义的数据。
  • 你有没有解决这个问题?我即将发布同样的问题。
  • 我选择了阻力最小的路径,并使用单个表(对单个类型进行建模)和多个连接表(对关系进行建模)。
  • 感谢您的回复。我找到了一个解决方案,可以让我利用我现有的设置。让我知道你的想法。

标签: nhibernate fluent-nhibernate


【解决方案1】:

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

我的场景有一个文档。各种各样的东西都会有文档——比如报告、项目等。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 类。

在我的情况下 - 我也只是将 Documents 映射到特定的表。这与其他方法相同 - 从GenericDocumentMapping 继承并指定表。唯一的区别是我没有引用父对象。

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

【讨论】:

  • 这个答案提出了一个合理的折衷方案和一个相当聪明的方法来解决这个问题。
【解决方案2】:

你可以使用 join 将其映射到多个表

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    相关资源
    最近更新 更多