C# 为什么不能使用父实体复合键的一部分引用子实体

C# 为什么不能使用父实体复合键的一部分引用子实体,c#,nhibernate,hibernate,composite-id,C#,Nhibernate,Hibernate,Composite Id,我正在尝试引用一些包含部分父复合键的子实体,但不是全部,为什么我不能?当我使用下面的映射而不是注释的映射时,就会发生这种情况 我得到以下错误 表中的外键 VolatileEventContent必须具有相同的 引用的列数 表中的主键 位置搜索视图 和VolatileEventContent映射文件 <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.

我正在尝试引用一些包含部分父复合键的子实体,但不是全部,为什么我不能?当我使用下面的映射而不是注释的映射时,就会发生这种情况

我得到以下错误

表中的外键 VolatileEventContent必须具有相同的 引用的列数 表中的主键 位置搜索视图

和VolatileEventContent映射文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
  <class name="Event" table="VolatileEventContent" select-before-update="false" optimistic-lock="none">
    <composite-id>
      <key-property name="LocationId" type="Int32"></key-property>
      <key-property name="ContentProviderId" type="Int32"></key-property>
    </composite-id>

    <property name="Description" type="String" not-null="true" update="false" insert="false"/>

    <property name="StartDate" type="DateTime" not-null="true" update="false" insert="false" />
    <property name="EndDate" type="DateTime" not-null="true" update="false" insert="false" />

    <property name="CreatedOn" type="DateTime" not-null="true" update="false" insert="false" />
    <property name="ModifiedOn" type="DateTime" not-null="false" update="false" insert="false" />

    <many-to-one name="Location" class="Location" column="LocationId" />

    <bag name="Artistes" table="EventArtiste" lazy="false" cascade="none">
      <key name="VolatileEventContentId" />
      <many-to-many class="Artiste" column="ArtisteId" ></many-to-many>
    </bag>
  </class>
</hibernate-mapping>

我从未使用过nhibernate,但我想映射与hibernate非常相似

如果您不希望一对多LocationSearchView-to-many-VolatileEventContent关联使用LocationSearchView id,则需要在行李的关键元素上定义将定义要使用的属性的属性ref:

<bag name="Events" table="VolatileEventContent" ...>
  <key property-ref="partialId">
    <column name="LocationId"></column>
    <column name="ContentProviderId"></column>
  </key>
  <one-to-many class="Event" column="VolatileEventContentId"></one-to-many>
</bag>
列属性对一对多标记有效吗

现在需要定义该名称的属性,类似于:

<properties name="partialId" insert="false" update="false">
  <property name="LocationId" type="Int32" update="false" insert="false"/>
  <property name="ContentProviderId" type="Int32" update="false" insert="false"/>
</properties>

您已经定义了LocationId和ContentProviderId。只需将这两个属性移到properties元素中。

错误是正确的。我猜您正在使用SchemaExport根据NHibernate映射生成表,因为您收到的错误听起来像是在创建表和外键的过程中发生的。SchemaExport将生成与以下类似的表。请注意代码中分散的解释:

CREATE TABLE LocationSearchView (
    LocationId int NOT NULL,
    ContentProviderId int NOT NULL,
    CategoryId int NOT NULL,

    /* ...other columns... */

    /* Note: Generated from LocationSearchView's "composite-id" element.  */
    PRIMARY KEY (LocationId, ContentProviderId, CategoryId)
);

/* Note: Table for the "Event" class. */
CREATE TABLE VolatileEventContent (
    LocationId int NOT NULL,
    ContentProviderId int NOT NULL,

    /* ...other columns... */

    /* Note: Generated from Event's "composite-id" element. */
    PRIMARY KEY (LocationId, ContentProviderId),
    /* Note: Generated from the "key" element of LocationSearchView's Events bag. */
    FOREIGN KEY (LocationId, ContentProviderId) REFERENCES LocationSearchView (LocationId, ContentProviderId)
);
。。。因此出现了错误。外键必须指向完整的主键或唯一键,而不仅仅是主键的一部分。整个键是3列,而不是2列。为什么NHibernate会将这些列用作外键?因为LocationSearchView的事件包的元素。指定从子项指向父项的列

让我们考虑当您或NHiBiNess尝试从这些表中选择时会发生什么。假设以下数据:

TABLE LocationSearchView LocationId ContentProviderId CategoryId ========== ================= ========== 1 3 5 1 3 6 1 4 5 1 4 6 2 3 5 2 3 6 2 4 5 2 4 6 一个LocationSearchView不可能有多个事件。相反,它应该是另一种方式。考虑到这些表,从Event到LocationSearchView确实存在一对多的关系


我不知道这个问题的正确解决方案是什么,因为我不知道您试图实现什么,但希望这有助于说明问题的确切原因。

首先,您的LocationSearchView映射中有一个错误 您将CategoryId列定义为属性和Composite-id的一部分。这是错误的,但不幸的是,在构建映射时未捕获该列,并且通常在查询对象时公开该列。检查

这可能会混淆映射解析器。我之所以说混乱,是因为在这两种映射中,您都依赖于反射和约定,这意味着更严格的编程方法:

您没有显式定义多对一和bag元素的class属性,而是希望NHibernate从类定义本身检测类类型。如果您在LocationSearchView类中设置了以下IList事件{get;set;}nhibernate,则您将期望找到已定义行李的LocationSearchView类,因此需要3列来映射集合 列名具有相同的属性名称,这使得开发更容易。实际上,这只会使映射的创建更容易,您只需进行一次或两次映射,但如果出现错误或更改,则更难检测出错误。
因此,让您的映射更丰富,并删除我在CategoryId中提到的错误,同时在您的帖子中包含类

你能把你对VolatileEventContent的映射也张贴出来吗?添加了额外的映射谢谢你的回复Daniel hbm文件代表了我的表格,我没有使用SchemaExport,不管它是什么,这是事件与LocationSearchView的关系我对SchemaExport有一个问题,它是一个基于NHibernate映射生成表的工具。我以为你使用它是因为外键。。。必须具有相同的列数。。。听起来像是在创建表和外键时发生的错误。您能提供此错误的堆栈跟踪吗?我对你桌子结构的猜测是不是不正确?我将更新我的答案,以解释为什么我认为您的表是这样。不幸的是,property ref不是一个可识别的属性: TABLE LocationSearchView LocationId ContentProviderId CategoryId ========== ================= ========== 1 3 5 1 3 6 1 4 5 1 4 6 2 3 5 2 3 6 2 4 5 2 4 6 TABLE VolatileEventContent LocationId ContentProviderId ========== ================= 1 3 1 4 2 3 2 4