引用同一列的两个多对一关系 NHibernate
Two many-to-one relationships referencing the same column NHibernate
过去半天一直在四处寻找,结果都干了。本质上,我正在处理遗留应用程序,预先存在的 NHibernate 配置将 DB 端的单个 属性 / 列映射到两个不同的 "many-to-one" 关系,因此映射到两个不同的 C# 属性。 tables categories
和 types
共享相同的主键/索引,但在 MySQL 或 NHibernate 中没有明确的关系。
以前这些 table 是 "read-only" 并且它在应用程序中有效,同时避免将其暴露为问题。但是,我最近的任务是允许用户修改和保留对 grid
table 的更改(为简洁起见,我没有列出其他属性)。
NHibernate 抛出了一个神秘的异常,我认为,这是因为它试图将两个单独的 "Domain" 级别对象保存到单个列引用中。我查看了 general_log
并且更新查询没有到达数据库。注释掉 .hbm.xml
配置文件中的 "Cat" 行解决了 "error",但是我如何修复映射使得 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`),
table grid
通过 MySQL 中的外键引用 table types
,但 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>
将尝试说服我的老板,这值得重组,因为数据库的整个区域都是一团糟,但这个 是 遗留应用程序;所以我想知道我的选择是什么,这取决于我们对未来发展的可用性。
编辑:试用 Radim Köhler 下面的建议。唯一的问题是 (a) 有人可以切换 Cat
的值并错误地认为他们已经对数据库进行了更改,但它不会被持久化。并且 (b) 如果有人更新 GridType
,它会更新数据库而不是缓存; Cat
将保持旧值,直到 NHibernate 再次从数据库中撤回(即 Cat
和 GridType
的 ID 将是 "de-synced",这是我问题的一部分)。
我正在试用的修复程序是 "when the GridType / Cat values on Grid are set, set the other one by fetching the appropriate ID from cache"。还将阻止某人设置其他 table.
中可能不存在的 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" />
过去半天一直在四处寻找,结果都干了。本质上,我正在处理遗留应用程序,预先存在的 NHibernate 配置将 DB 端的单个 属性 / 列映射到两个不同的 "many-to-one" 关系,因此映射到两个不同的 C# 属性。 tables categories
和 types
共享相同的主键/索引,但在 MySQL 或 NHibernate 中没有明确的关系。
以前这些 table 是 "read-only" 并且它在应用程序中有效,同时避免将其暴露为问题。但是,我最近的任务是允许用户修改和保留对 grid
table 的更改(为简洁起见,我没有列出其他属性)。
NHibernate 抛出了一个神秘的异常,我认为,这是因为它试图将两个单独的 "Domain" 级别对象保存到单个列引用中。我查看了 general_log
并且更新查询没有到达数据库。注释掉 .hbm.xml
配置文件中的 "Cat" 行解决了 "error",但是我如何修复映射使得 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`),
table grid
通过 MySQL 中的外键引用 table types
,但 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>
将尝试说服我的老板,这值得重组,因为数据库的整个区域都是一团糟,但这个 是 遗留应用程序;所以我想知道我的选择是什么,这取决于我们对未来发展的可用性。
编辑:试用 Radim Köhler 下面的建议。唯一的问题是 (a) 有人可以切换 Cat
的值并错误地认为他们已经对数据库进行了更改,但它不会被持久化。并且 (b) 如果有人更新 GridType
,它会更新数据库而不是缓存; Cat
将保持旧值,直到 NHibernate 再次从数据库中撤回(即 Cat
和 GridType
的 ID 将是 "de-synced",这是我问题的一部分)。
我正在试用的修复程序是 "when the GridType / Cat values on Grid are set, set the other one by fetching the appropriate ID from cache"。还将阻止某人设置其他 table.
中可能不存在的 gridtype / catpublic 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" />