FluentNHibernate 复合外键的映射

发布于 2024-08-28 08:56:48 字数 1734 浏览 1 评论 0原文

我有一个现有的数据库模式,并希望用 Fluent.NHibernate 替换自定义数据访问代码。数据库架构无法更改,因为它已存在于发货产品中。如果领域对象没有改变或只改变了最小限度,那就更好了。

我在映射一个不寻常的架构构造时遇到问题,该架构用以下表结构说明:

CREATE TABLE [Container] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Container] PRIMARY KEY (
    [ContainerId] ASC
  )
)

CREATE TABLE [Item] (
  [ItemId]      [uniqueidentifier] NOT NULL,
  [ContainerId] [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Item] PRIMARY KEY (
    [ContainerId] ASC,
    [ItemId] ASC
  )
)

CREATE TABLE [Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [PropertyId]  ASC
  )
)

CREATE TABLE [Item_Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [ItemId]      [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Item_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [ItemId]      ASC,
    [PropertyId]  ASC
  )
)

CREATE TABLE [Container_Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Container_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [PropertyId]  ASC
  )
)

现有的域模型具有以下类结构:

alt text http://yuml.me/4e2bcb95

Property 类包含表示属性名称和值的其他成员。 ContainerProperty 和 ItemProperty 类没有其他成员。它们的存在只是为了识别财产的所有者。 Container 和 Item 类具有分别返回 ContainerProperty 和 ItemProperty 集合的方法。此外,Container 类有一个方法,该方法返回对象图中所有 Property 对象的集合。我最好的猜测是,这要么是一种便捷方法,要么是从未删除的遗留方法。

业务逻辑主要与 Item(作为聚合根)一起工作,并且仅在添加或删除 Item 时与 Container 一起工作。

我已经尝试了多种技术来绘制此图,但没有任何效果,因此除非有人要求,否则我不会将它们包含在这里。你会如何映射这个?

I have an existing database schema and wish to replace the custom data access code with Fluent.NHibernate. The database schema cannot be changed since it already exists in a shipping product. And it is preferable if the domain objects did not change or only changed minimally.

I am having trouble mapping one unusual schema construct illustrated with the following table structure:

CREATE TABLE [Container] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Container] PRIMARY KEY (
    [ContainerId] ASC
  )
)

CREATE TABLE [Item] (
  [ItemId]      [uniqueidentifier] NOT NULL,
  [ContainerId] [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Item] PRIMARY KEY (
    [ContainerId] ASC,
    [ItemId] ASC
  )
)

CREATE TABLE [Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [PropertyId]  ASC
  )
)

CREATE TABLE [Item_Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [ItemId]      [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Item_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [ItemId]      ASC,
    [PropertyId]  ASC
  )
)

CREATE TABLE [Container_Property] (
  [ContainerId] [uniqueidentifier] NOT NULL,
  [PropertyId]  [uniqueidentifier] NOT NULL,
  CONSTRAINT [PK_Container_Property] PRIMARY KEY (
    [ContainerId] ASC,
    [PropertyId]  ASC
  )
)

The existing domain model has the following class structure:

alt text http://yuml.me/4e2bcb95

The Property class contains other members representing the property's name and value. The ContainerProperty and ItemProperty classes have no additional members. They exist only to identify the owner of the Property. The Container and Item classes have methods that return collections of ContainerProperty and ItemProperty respectively. Additionally, the Container class has a method that returns a collection of all of the Property objects in the object graph. My best guess is that this was either a convenience method or a legacy method that was never removed.

The business logic mainly works with Item (as the aggregate root) and only works with a Container when adding or removing Items.

I have tried several techniques for mapping this but none work so I won't include them here unless someone asks for them. How would you map this?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别忘他 2024-09-04 08:56:48

映射应如下所示:

public sealed class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
        Table("Categories");
        CompositeId()
            .KeyProperty(c => c.ItemId, "ItemId")
            .KeyProperty(c => c.CategoryId, "CategoryId");
    }
}

注意:

  1. 类别实体类应覆盖 Equals()GetHashCode() 方法
  2. 所有属性和方法都应为虚拟/覆盖!

-

public class Category
{
    public virtual int ItemId { get; set; }
    public virtual int CategoryId { get; set; }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Category)) return false;
        return Equals((Category) obj);
    }

    public virtual bool Equals(Category other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.ItemId == ItemId && other.CategoryId == CategoryId;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (ItemId*397) ^ CategoryId;
        }
    }
}

Mapping should look this way:

public sealed class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
        Table("Categories");
        CompositeId()
            .KeyProperty(c => c.ItemId, "ItemId")
            .KeyProperty(c => c.CategoryId, "CategoryId");
    }
}

Note:

  1. Category entity class should override Equals() and GetHashCode() methods
  2. All properties and methods should be virtual / overwritten!

-

public class Category
{
    public virtual int ItemId { get; set; }
    public virtual int CategoryId { get; set; }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Category)) return false;
        return Equals((Category) obj);
    }

    public virtual bool Equals(Category other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.ItemId == ItemId && other.CategoryId == CategoryId;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (ItemId*397) ^ CategoryId;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文