Последние полдня искали и подошли dry. По сути, я работаю над унаследованным приложением, ранее существовавшая конфигурация NHibernate отображала одно свойство / столбец на конце DB в два разных отношения «многие-к-одному» и, следовательно, два разных свойства C#. Таблицы categories
и types
используют одни и те же первичные ключи / индексы, но в MySQL или NHibernate нет явной связи.
Раньше эти таблицы были «только для чтения», и они работали в приложении, избегая выставлять это как проблему. Но недавно мне было поручено разрешить пользователям изменять и сохранять изменения в таблице grid
(имеет другие свойства, которые я не перечислил для краткости).
NHibernate выдал исключение crypti c, связанное, я полагаю, с тем, что он пытается сохранить два отдельных объекта уровня «Домен» в одну ссылку на столбец. Я просмотрел general_log
и запрос на обновление не дошел до базы данных. Закомментирование строки «Cat» в конфигурационном файле .hbm.xml
устранило «ошибку», но как я могу исправить отображение таким образом, чтобы Cat
и GridType
должны иметь одинаковое значение ID
, и я могу сохранить grid
переходит обратно в БД?
public class Grid
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual GridType GridType { get; set; }
public virtual Cat Cat { get; set; }
...
}
Схема БД выглядит следующим образом (поддерживая существующую странную настройку):
CREATE TABLE `categories`
`CatID` smallint(4) NOT NULL,
`Name` varchar(50) DEFAULT NULL,
...
PRIMARY KEY (`CatID`)
CREATE TABLE `types`
`TypeID` smallint(4) NOT NULL,
`Name` varchar(50) DEFAULT NULL,
...
PRIMARY KEY (`TypeID`)
CREATE TABLE `grid`
`GridID` smallint(6) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) DEFAULT NULL,
`TypeID` smallint(4) NOT NULL,
...
PRIMARY KEY (`GridID`),
KEY `GridTypeId` (`TypeID`),
CONSTRAINT `GridTypeId` FOREIGN KEY (`TypeID`) REFERENCES `types` (`TypeID`),
Таблица grid
ссылается на таблицу types
через внешний ключ в MySQL , но ничто на DB-конце не связывает его с categories
. Конфигурация NHibernate в настоящее время настроена так, за исключением того, что ранее конфигурация "grid" ранее была mutable="false"
и cache usage="read-only"
:
<class name="Grid, Domain" table="grid" lazy="true">
<cache usage="read-write" />
<id name="Id" column="GridID" unsaved-value="0">
<generator class="identity" />
</id>
...
<many-to-one name="GridType" column="TypeID" fetch="join" not-null="true" />
<many-to-one name="Cat" column="TypeID" not-null="true" />
</class>
<class name="Cat, Domain" table="categories" lazy="true" mutable="false">
<cache usage="read-only"/>
<id name="Id" column="CatID" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Name" />
...
</class>
<class name="GridType, Domain" table="types" mutable="false">
<cache usage="read-only"/>
<id name="Id" column="TypeID"/>
<property name="Name" />
...
</class>
. Попробую убедить моего босса, что это стоит реструктурировать. потому что вся эта область БД - беспорядок, но это - устаревшее приложение; поэтому я хочу знать, какие у меня варианты, в зависимости от того, как выглядит наша готовность к будущему развитию.
Редактировать : Судебный процесс, предложенный Радимом Келером ниже. Единственным недостатком было то, что (a) Кто-то мог переключить значение Cat
и ошибочно полагать, что он внес изменения в БД, но это не будет сохраняться. И (б) если кто-то обновит GridType
, он обновит БД, но не кеш; Cat
будет оставаться старым значением до тех пор, пока NHibernate снова не будет извлечен из БД (т.е. идентификаторы Cat
и GridType
будут "не синхронизированы", что было частью моего вопроса).
Исправление I Испытание "когда значения GridType / Cat на Grid установлены, установите другое, выбрав соответствующий идентификатор из кэша". Также будет препятствовать тому, чтобы кто-то установил тип сетки / кошку, которая может не существовать в другой таблице.
public class Grid {
...
private GridType _gridType;
private Cat _cat;
public virtual GridType GridType
{
get => _gridType;
set
{
var cat = _catRepository.GetById(value.Id);
_cat = cat ?? throw new InvalidOperationException("GridType is not valid Cat");
_gridType = value;
}
}
И повторите выше для public virtual Cat Cat
. Если кто-то видит проблему с этим, пожалуйста, не стесняйтесь оставлять комментарий.