NHibernate - 使用附加数据对相同类型的实体之间的关系进行建模

发布于 2024-12-17 07:06:07 字数 2479 浏览 0 评论 0原文

我几乎用尽了谷歌,还没有弄清楚如何完成我的数据模型的映射。更重要的是,我还没有真正找到一种对域进行建模的好方法。

这是我拥有的数据:

CREATE TABLE Ticket (
    Id int IDENTITY(1,1) NOT NULL,
    Name nvarchar(250) NULL
    -- And a lot of other columns
)

现在每个工单可以有任意数量的相关工单,但关键是这种关系是对等关系,而不是父子关系。这是关联表:

CREATE TABLE TicketRelationship (
    TicketA_Id int NOT NULL,
    TicketB_Id int NOT NULL,
    Description nvarchar(max) NULL
)

这里的想法是,当查看带有其他相关票证的票证时,我不仅可以查看相关票证,还可以查看该关系的描述。无论我查看的是票证 A 还是票证 B,我都能够看到这一点。

问题是如何 1) 在我的域中以不会创建两个 TicketRelationship 每个双向关系的记录,以及 2) 如何使用 NHibernate 映射该域模型(我使用的是 Fluent NH)。

理想情况下,票证类的工作方式如下:

public class Ticket : EntityBase<Ticket>, IAggregateRoot
{
    public virtual string Name { get; set; }
    public virtual IDictionary<Ticket, string> RelatedTickets { get; set; }
}

IDictionary 中的字符串是关系表中的 Description 列。

现在的挑战是如何对此进行映射,以便相关票证显示在列表中,无论它是否在 TicketA_IdTicketB_id 列中引用。

如果这是不可能的,那么我可以拆分域模型,使类看起来像这样:

public class Ticket : EntityBase<Ticket>, IAggregateRoot
{
    public virtual string Name { get; set; }
    public virtual IDictionary<Ticket, string> ReferencesTickets { get; set; }
    public virtual IDictionary<Ticket, string> ReferencedByTickets { get; set; }
}

这可能会稍微简化一些事情,但是使用单个关联表我无法使映射正常工作。我尝试了这个,但是 FNH 不允许我指定父键列和子键列:

        mapping.HasMany(x => x.ReferencesTickets)
            .Table("TicketRelationships")
            .AsEntityMap()
            .KeyColumn("TicketA_Id")
            .Element("Description");
        
        mapping.HasMany(x => x.ReferencedByTickets)
            .Table("TicketRelationships")
            .AsEntityMap()
            .KeyColumn("TicketB_Id")
            .Element("Description");

有什么想法可以让这个工作起作用吗?

更新:

我能够通过调整映射来使后备方案正常工作:

        mapping.HasMany(x => x.ReferencesTickets)
            .Table("TicketRelationships")
            .AsEntityMap("TicketB_Id")
            .KeyColumn("TicketA_Id")
            .Element("Description");
        
        mapping.HasMany(x => x.ReferencedByTickets)
            .Table("TicketRelationships")
            .AsEntityMap("TicketA_Id")
            .KeyColumn("TicketB_Id")
            .Element("Description");

但是,如果有一种方法可以使用单个 IDictionary 来简化它,我很乐意听到任何建议。

I've pretty much exhausted Google and haven't figured out how to accomplish the mapping for my data model. More than that I haven't really figured out a great way to model the domain.

Here's the data I have:

CREATE TABLE Ticket (
    Id int IDENTITY(1,1) NOT NULL,
    Name nvarchar(250) NULL
    -- And a lot of other columns
)

Now each Ticket can have any number of related tickets, but the key is that this relationship is a peer relationship, not a parent-child. Here's the association table:

CREATE TABLE TicketRelationship (
    TicketA_Id int NOT NULL,
    TicketB_Id int NOT NULL,
    Description nvarchar(max) NULL
)

The idea here is that when viewing a Ticket with other related tickets, I'll be able to view not only the related tickets but the description of that relationship. And I'll be able to see that whether I'm looking at Ticket A or Ticket B.

The problem is how to 1) model this in my domain in such a way that doesn't create two TicketRelationship records for each two-way relationship, and 2) how to map that domain model with NHibernate (I'm using Fluent NH).

Ideally, this is how the ticket class would work out:

public class Ticket : EntityBase<Ticket>, IAggregateRoot
{
    public virtual string Name { get; set; }
    public virtual IDictionary<Ticket, string> RelatedTickets { get; set; }
}

Where the string in the IDictionary is the Description column in the relationship table.

The challenge now is how to map this such that the related ticket shows up in the list regardless of whether it's referenced in the TicketA_Id or TicketB_id columns.

If this is not possible, then I could split the domain model such that the class appears like this:

public class Ticket : EntityBase<Ticket>, IAggregateRoot
{
    public virtual string Name { get; set; }
    public virtual IDictionary<Ticket, string> ReferencesTickets { get; set; }
    public virtual IDictionary<Ticket, string> ReferencedByTickets { get; set; }
}

This might simplify things a bit, but with a single association table I haven't been able to get the mappings to work. I tried this, but FNH doesn't let me specify the parent and child key columns:

        mapping.HasMany(x => x.ReferencesTickets)
            .Table("TicketRelationships")
            .AsEntityMap()
            .KeyColumn("TicketA_Id")
            .Element("Description");
        
        mapping.HasMany(x => x.ReferencedByTickets)
            .Table("TicketRelationships")
            .AsEntityMap()
            .KeyColumn("TicketB_Id")
            .Element("Description");

Any ideas how I can make this work?

Update:

I was able to get the fallback scenario to work by adjusting the mappings to this:

        mapping.HasMany(x => x.ReferencesTickets)
            .Table("TicketRelationships")
            .AsEntityMap("TicketB_Id")
            .KeyColumn("TicketA_Id")
            .Element("Description");
        
        mapping.HasMany(x => x.ReferencedByTickets)
            .Table("TicketRelationships")
            .AsEntityMap("TicketA_Id")
            .KeyColumn("TicketB_Id")
            .Element("Description");

However, if there's a way to have a single IDictionary to simplify it I'd love to hear any suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文