简体   繁体   English

复合外键的FluentNHibernate映射

[英]FluentNHibernate mapping of composite foreign keys

I have an existing database schema and wish to replace the custom data access code with Fluent.NHibernate. 我有一个现有的数据库架构,希望用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 替代文字http://yuml.me/4e2bcb95

The Property class contains other members representing the property's name and value. Property类包含其他代表属性名称和值的成员。 The ContainerProperty and ItemProperty classes have no additional members. ContainerProperty和ItemProperty类没有其他成员。 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. Container和Item类具有分别返回ContainerProperty和ItemProperty的集合的方法。 Additionally, the Container class has a method that returns a collection of all of the Property objects in the object graph. 此外,Container类具有一个方法,该方法返回对象图中所有Property对象的集合。 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. 业务逻辑主要与Item(作为聚合根)一起使用,并且仅在添加或删除Items时与Container一起使用。

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? 您将如何映射?

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 类别实体类应重写Equals()GetHashCode()方法
  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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM