为什么当我尝试使用 NHibernate 会话保存到包含复合键的网桥表时出现外键冲突

本文关键字:网桥 复合 冲突 包含 保存 会话 NHibernate 为什么 | 更新日期: 2023-09-27 17:57:05

我们的办公室团队正在 ASP.NET 使用.NET Framework 4和NHibernate 3.3.1的项目

我有一个名为 AllResourcesInfo 的 POCO 域类(它最终映射到数据库中的资源表,该表内部连接到其他一些表,但为了简单起见,我们只是说 AllResourcesInfo 映射到资源表)。

我还有一个名为 Section 的 POCO 域类(它最终映射到数据库中的 Section 表)

我还有一个名为ResourcesInSectionBridge的POCO域类(它最终映射到数据库中名为ResourcesInSectionBridge的桥接表)

正如命名约定所建议的那样,ResourcesInSectionBridge 是 Resource 和 Section 之间的桥接表。

由于 ResourcesInSectionBridge 包含一个复合键,

因此我创建了一个名为 ResourcesInSectionIdentifier 的 POCO 复合键标识符,并定义了 Equals(object obj) 方法和 GetHashCode 方法。

当我使用 NHibernate Session 为 ResourcesInSectionBridge 表保存一个新条目时,我收到一个错误:

异常详细信息:System.Data.SqlClient.SqlException:INSERT 语句与 FOREIGN KEY 约束"FK_Resources_Resou__22CA2527"冲突。冲突发生在数据库"perls",表"dbo。资源",列"资源数据库 ID"。该语句已终止。

AllResourcesInfo.hbm.xml 的映射如下所示:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
  <class name="AllResourcesInfo" table="Resources">
    <id name="ResourceDatabaseID">
      <generator class="guid" />
    </id>
    <property name="ResourceName" />
    <property name="DescriptionOfResource" />
    <property name="UserId" />
    <property name="DepartmentDatabaseID" />
    <property name="ResourceStatus" />
    <property name="isRemoved" />
    <property name="isSubmitted" />
    <property name="ResourcePlacement" />
    <property name="ResourceType" />
    <property name="ParentResourceID" />
    <joined-subclass     name="Imageitems">
      <key column="ResourceDatabaseID"/>
      <property column="DirectoryPathToFile" name="location"/>
      <property column="ImageIconPath" name="link"/>
      <property column="YearOfResource" name="YearOfResource"/>
      <property column="ArtistAuthor" name="ArtistAuthor"/>
      <property column="UploadDate" name="UploadDate"/>
      <property column="ImageitemDatabaseID" name="NativeItemDatabaseID"/>
    </joined-subclass>
    <joined-subclass     name="UriItems">
      <key column="ResourceDatabaseID"/>
      <property column="uriIconPath" name="location"/>
      <property column="UriLink" name="link"/>
      <property column="YearOfResource" name="YearOfResource"/>
      <property column="ArtistAuthor" name="ArtistAuthor"/>
      <property column="UploadDate" name="UploadDate"/>
      <property column="UriItemDatabaseID" name="NativeItemDatabaseID"/>
    </joined-subclass>
  </class>
</hibernate-mapping>

Section.hbm.xml 的映射如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
   <class name="Section"  table="Section">
     <id name="SectionDatabaseID">
       <generator class="guid" />
     </id>
    <many-to-one name="Courses"
   column="CourseDatabaseID" class="Courses"
  fetch="select"/>
     <many-to-one name="instructorUser" column="UserId" class="Users"
     fetch="select"/>
    <many-to-one name="term"
   column="TermDatabaseID" class="Term"
   fetch="select"/>
     <property  column="SectionCode" name="SectionCode" />
    <set name="setOfTutorials" inverse="false" lazy="true" fetch="select" >
      <key column="TutorialDatabaseID"/>
      <one-to-many class="Tutorial"/>
    </set>
  </class>
 </hibernate-mapping>

最后,我们的 ResourcesInSectionBridge.hbm.xml 映射文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="PivotServer"
               namespace="PivotServer.Domain"
               auto-import="false">
  <class name="ResourcesInSectionBridge" table="ResourcesInSectionBridge"  lazy="true" >
     <composite-id name="ResourcesInSectionIdentifier" class="ResourcesInSectionIdentifier">
        <key-property name="ResourceDatabaseID" column="ResourceDatabaseID" type="Guid"  />
       <key-property name="SectionDatabaseID" column="SectionDatabaseID" type="Guid"   />
      </composite-id>
     <many-to-one name="AllResourcesInfo" class="AllResourcesInfo" cascade="none" insert="false" update="false">
       <column name="ResourceDatabaseID"></column>
       <column name="ResourceDatabaseID"></column>
     </many-to-one>
    <many-to-one name="Section" class="Section" cascade="none" insert="false" update="false">
       <column name="SectionDatabaseID"></column>
       <column name="SectionDatabaseID"></column>
     </many-to-one>
  </class>
 </hibernate-mapping>

最后,尝试在 ResourcesInSectionBridge 表中创建一个条目的 C# 代码如下所示:

ResourcesInSectionBridge resInSectionBridgeEntity = new ResourcesInSectionBridge();
ResourcesInSectionIdentifier resInSectionIdentifier = new ResourcesInSectionIdentifier();
resInSectionIdentifier.ResourceDatabaseID = aSpecificResource.ResourceDatabaseID;
resInSectionIdentifier.SectionDatabaseID = sectionOfInterest.SectionDatabaseID;
resInSectionBridgeEntity.ResourcesInSectionIdentifier = resInSectionIdentifier;
resInSectionBridgeEntity.Section = sectionOfInterest;
resInSectionBridgeEntity.AllResourcesInfo = aSpecificResource;
using (ISession session = NHibernateHelper.OpenSession())
{
        session.Evict(aSpecificResource);
        session.Evict(sectionOfInterest);
        session.Clear();
        using (ITransaction transaction = session.BeginTransaction())
        {
                session.Save(resInSectionBridgeEntity);
                transaction.Commit();
        }
} // end of using (ISession session = NHibernateHelper.OpenSession())

当我使用 NHibernate Session 为 ResourcesInSectionBridge 表保存一个新条目时,我收到一个错误:

异常详细信息:System.Data.SqlClient.SqlException:INSERT 语句与 FOREIGN KEY 约束"FK_Resources_Resou__22CA2527"冲突。冲突发生在数据库"perls",表"dbo。资源",列"资源数据库 ID"。该语句已终止。

你能解释一下为什么会抛出这个错误吗? 另外,您能否建议我如何解决问题?

为什么当我尝试使用 NHibernate 会话保存到包含复合键的网桥表时出现外键冲突

您看到的错误来自数据库,它指出Resources表中不存在ResourceDatabaseID键的值。对桥接表所做的任何条目都必须在两个源表插入其项目之后(如果它们尚不存在)。

您需要正确填充ResourceSection实体,以便插入到桥表中才能正常工作。 查看这些示例中的多对多映射的示例代码,了解与要实现的内容类似的内容。您可以下载示例,而无需其产品。