Почему я получаю нарушение внешнего ключа, когда пытаюсь использовать NHibernate Session для сохранения в таблицу мостов, содержащую составной ключ?
Наша офисная команда работает над проектом ASP.NET, который использует.NET Framework 4 и NHibernate 3.3.1
У меня есть класс домена POCO с именем AllResourcesInfo (который в конечном итоге сопоставляется с таблицей ресурсов в базе данных, которая внутренне соединена с некоторыми другими таблицами, но для простоты скажем, что AllResourcesInfo сопоставляется с таблицей ресурсов).
У меня также есть класс домена POCO под названием Section (который в конечном итоге отображается на таблицу Section в базе данных).
У меня также есть класс домена POCO с именем ResourcesInSectionBridge (который в конечном итоге сопоставляется с таблицей мостов в базе данных с именем ResourcesInSectionBridge)
Как следует из соглашения об именах, ResourcesInSectionBridge - это мостовая таблица между ресурсом и разделом.
Поскольку ResourcesInSectionBridge содержит составной ключ, я создал идентификатор составного ключа POCO с именем ResourcesInSectionIdentifier, а также определил метод Equals(object obj) и метод GetHashCode.
Когда я использую NHibernate Session для сохранения новой записи для таблицы ResourcesInSectionBridge, я получаю сообщение об ошибке:
Сведения об исключении: System.Data.SqlClient.SqlException: оператор INSERT конфликтует с ограничением FOREIGN KEY "FK_Resources_Resou__22CA2527". Конфликт произошел в базе данных "perls", таблице "dbo.Resources", столбце "ResourceDatabaseID". Заявление было прекращено.
Отображение для 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>
Наконец, наш код C#, который пытается создать запись в таблице ResourcesInSectionBridge, выглядит следующим образом:
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.Resources", столбце "ResourceDatabaseID". Заявление было прекращено.
Не могли бы вы объяснить, почему эта ошибка возникает? Кроме того, не могли бы вы подсказать, как мне решить проблему?
1 ответ
Ошибка, которую вы видите из базы данных, и это говорит о том, что значение для ResourceDatabaseID
Ключ не существует в Resources
Таблица. Любая запись, сделанная для таблицы-моста, должна быть после того, как две исходные таблицы вставили свои элементы, если они еще не существуют.
Вы должны правильно заполнить оба Resource
а также Section
сущности для вставки в таблицу мостов для работы. Посмотрите на пример кода для сопоставления "многие ко многим" из этого примера, чтобы найти нечто похожее на то, что вы пытаетесь достичь. Вы можете скачать образцы, не требуя их продукта.