c# - 引用同一列 NHibernate 的两个多对一关系
问题描述
在过去的半天里一直在四处寻找并且已经干了。本质上,我正在开发一个遗留应用程序,预先存在的 NHibernate 配置将 DB 端上的单个属性/列映射到两个不同的“多对一”关系,因此是两个不同的 C# 属性。这些表共享相同categories
的types
主键/索引,但在 MySQL 或 NHibernate 中没有明确的关系。
以前这些表是“只读的”,它在应用程序中工作,同时避免将其作为问题暴露。但是,我最近的任务是允许用户修改和保留对grid
表的更改(为了简洁起见,我没有列出其他属性)。
我相信 NHibernate 抛出了一个神秘的异常,它试图将两个单独的“域”级别对象保存到单个列引用中。我查看general_log
了更新查询并没有到达数据库。注释掉.hbm.xml
配置文件中的“Cat”行解决了“错误”,但是如何修复映射,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; }
...
}
DB 模式如下所示(维护现有的怪异设置):
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
表通过 MySQL 中的外键引用该表types
,但 DB 端没有将其与categories
. NHibernate 配置当前是这样设置的,唯一的例外是之前的“网格”配置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>
将尝试说服我的老板这值得重组,因为数据库的整个区域都是一团糟,但这是一个遗留应用程序;所以我想知道我的选择是什么,这取决于我们未来发展的可用性。
编辑:试用 Radim Köhler 下面的建议。唯一的问题是(a)有人可以切换值Cat
并错误地认为他们已经对数据库进行了更改,但它不会被持久化。并且(b)如果有人更新GridType
了,它会更新数据库而不是缓存;Cat
将保持旧值,直到 NHibernate 再次从数据库中撤出(即 IDCat
和GridType
将被“取消同步”,这是我的问题的一部分)。
我正在尝试的修复是“当设置 Grid 上的 GridType / Cat 值时,通过从缓存中获取适当的 ID 来设置另一个”。还将阻止某人设置另一个表中可能不存在的 gridtype / cat。
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
。如果有人看到这方面的问题,请随时发表评论。
解决方案
我们可以将映射中的一列用于多种用途...但只有一个属性可以编辑...所有其他属性必须是只读的。我们可以用insert="false" update="false"
这适用于我们的情况:
<many-to-one name="GridType" column="TypeID" ... />
<many-to-one name="Cat" column="TypeID" insert="false" update="false" />
推荐阅读
- r - ggplot histogram colour by group not working
- android - Paging Library With Room And Raw Query
- java - I want to get data from fire store in to android studio
- facebook - Use Cookie to Authenticate a Facebook Account for Remote Screenshot
- javascript - how to add backroung images to the polygon series amchart
- java - org.hibernate.hql.internal.ast.QuerySyntaxException hibernate entity is not mapped
- python - mypy 使用 --strict-equality 将其实例视为 Any 的类
- java - RCP Client using ECF JaxRS (Jersey) starts on OpenWebstart but not original/Oracle Webstart (Java 8)
- vue.js - Vuejs + vue-html2pdf:未定义窗口
- environment-variables - 使用 repo 机密在 gh 操作中创建 .env 文件