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

发布于 2024-08-22 19:44:38 字数 3503 浏览 4 评论 0原文

我试图用部分父复合键而不是全部来引用一些子实体,为什么不能呢?当我使用以下映射而不是注释的映射时,会发生这种情况。

我收到以下错误

表中的外键 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="LocationSearchView" table="LocationSearchView">

    <composite-id>
      <key-property name="LocationId" type="Int32"></key-property>
      <key-property name="ContentProviderId" type="Int32"></key-property>
      <key-property name="CategoryId" type="Int32"></key-property>
    </composite-id>

    <property name="CompanyName" type="String" not-null="true" update="false" insert="false"/>
    <property name="Description" type="String" not-null="true" update="false" insert="false"/>
    <property name="CategoryId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="ContentProviderId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="LocationId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="Latitude" type="Double"  update="false" insert="false" />
    <property name="Longitude" type="Double"  update="false" insert="false" />

    <bag name="Events" table="VolatileEventContent" where="DeactivatedOn IS NULL" order-by="StartDate DESC" lazy="false" cascade="none">
      <key>
        <column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <!--<column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <column name="CategoryId"></column>-->
      </key>
      <one-to-many class="Event" column="VolatileEventContentId"></one-to-many>
    </bag>

  </class>
</hibernate-mapping>

和 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>

I am trying to reference some child entities with part of the parents composite key not all of it, why cant I? This happens when I use the following mapping instead of that which is commented.

I get the following error

Foreign key in table
VolatileEventContent must have same
number of columns as referenced
primary key in table
LocationSearchView

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
  <class name="LocationSearchView" table="LocationSearchView">

    <composite-id>
      <key-property name="LocationId" type="Int32"></key-property>
      <key-property name="ContentProviderId" type="Int32"></key-property>
      <key-property name="CategoryId" type="Int32"></key-property>
    </composite-id>

    <property name="CompanyName" type="String" not-null="true" update="false" insert="false"/>
    <property name="Description" type="String" not-null="true" update="false" insert="false"/>
    <property name="CategoryId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="ContentProviderId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="LocationId" type="Int32" not-null="true" update="false" insert="false"/>
    <property name="Latitude" type="Double"  update="false" insert="false" />
    <property name="Longitude" type="Double"  update="false" insert="false" />

    <bag name="Events" table="VolatileEventContent" where="DeactivatedOn IS NULL" order-by="StartDate DESC" lazy="false" cascade="none">
      <key>
        <column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <!--<column name="LocationId"></column>
        <column name="ContentProviderId"></column>
        <column name="CategoryId"></column>-->
      </key>
      <one-to-many class="Event" column="VolatileEventContentId"></one-to-many>
    </bag>

  </class>
</hibernate-mapping>

And VolatileEventContent mapping file

<?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>

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

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

发布评论

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

评论(3

脸赞 2024-08-29 19:44:38

错误是正确的。我猜测您正在使用 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 将这些列用作外键?由于 LocationSearchViewEvents 包中的 元素。 指定从 中的哪些列指向

让我们考虑一下当您(或 NHibernate)尝试从这些表中进行选择时可能会发生什么。假设以下数据:

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

“一个”LocationSearchView 不可能拥有“多个”Event。相反,应该是相反的。给定这些表,从 EventLocationSearchView 确实存在一对多关系。

我不知道这个问题的正确解决方案是什么,因为我不知道你想要完成什么,但希望这有助于阐明问题到底是什么。

The error is correct. I'm guessing that you are using SchemaExport to generate your tables based on the NHibernate mappings, since the error you are receiving sounds like it would occur during the creation of your tables and foreign keys. SchemaExport would produce tables similar to the following (please note the explanations scattered throughout the code):

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)
);

... hence the error. A foreign key must point to a complete primary or unique key - not just part of a primary key. The whole key is 3 columns, not 2. Why would NHibernate use those columns for the foreign key? Because of the <key> element of LocationSearchView's Events bag. <key> specifies which columns from the child point back to the parent.

Let's consider what might happen when you (or NHibernate) try to select from these tables. Assume the following data:

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

It is not possible for "one" LocationSearchView to have "many" Events. Rather, it should be the other way around. Given these tables, there is really a one-to-many relationship from Event to LocationSearchView.

I don't know what the correct solution to this problem is, because I don't know what you are trying to accomplish, but hopefully this helps to illuminate what exactly the problem is.

回忆那么伤 2024-08-29 19:44:38

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

如果您不希望一对多(LocationSearchView 到多个 VolatileEventContent)关联使用 LocationSearchView id,则需要在包的关键元素上定义属性“property-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。只需将这两个属性移动到属性元素内即可。

I've never used nhibernate, but i guess mapping is quite similar the hibernate ones.

If you don't want your one-to-many (LocationSearchView to many VolatileEventContent) association to use the LocationSearchView id, you need to define on the key element of the bag the attribute "property-ref" that will define the property to use instead :

<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>

(column attribute is valid on a one-to-many tag ?)

Now you need to define a property of that name, something like that :

<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>

You have already defined LocationId and ContentProviderId. Just move the these two properties inside the properties element.

嗼ふ静 2024-08-29 19:44:38

首先,您的“LocationSearchView”映射存在错误
您将 CategoryId 列定义为属性和 Composite-id 的一部分。这是错误的,但不幸的是,它在构建映射时没有被捕获,并且通常在查询对象时被暴露。检查 IndexOutOfRangeException 深入 NHibernate 的内部

它可能使映射解析器感到困惑。我之所以说令人困惑,是因为在您的映射中,您都依赖于反射和约定,这意味着更严格的编程方法:

  1. 您没有显式定义 class 属性。 code>many-to-one 和 bag 元素,但您希望 NHibernate 从类定义本身检测类类型。如果万一您在类 LocationSearchView 中设置了以下 IList:事件 {get;set;} nhibernate 希望找到定义的 bagLocationSearchView 类,因此需要 3 列来映射集合
  2. 您有列名称具有相同的属性名称,这使得开发更容易(实际上,它只会使创建映射变得更容易,无论如何,您只需要创建一次或两次),但如果出现错误或更改,则更难检测出问题所在。

因此,让您的映射更丰富并删除我在 CategoryId 中提到的错误,同时在您的帖子中包含这些类!

First of all you have an error in your mapping for "LocationSearchView"
You define the CategoryId column both as a Property and part of the Composite-id. This is wrong but unfortunately it is not caught when building the mapping and is usually exposed when querying the object. check IndexOutOfRangeException Deep in the bowels of NHibernate

It could be confusing the mapping parser. And i am saying confusing because in both your mappings you rely on Reflection and Convention which imply a more disciplined programming methodology:

  1. You don't explicitly define the class attribute of the many-to-one and bag elements but instead you expect from NHibernate to detect the class type from the class definition itself. If by any chance you have set in the class LocationSearchView the following IList<LocationSearchView> Events {get;set;} nhibernate would expect to find the LocationSearchView class for the defined bag and hence require the 3 columns to map the collection
  2. You have the same property names for the column names which makes development easier (it actually only makes easier the creation of mappings which you only make once or twice anyway) but in case of errors or changes it makes it harder to detect what went wrong.

So, make your mappings richer and remove the error i mentioned with CategoryId, also include the classes in your post!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文