NHibernate 使用复合键将两个表连接成一个实体
我有以下数据结构:
+---------+
|Resume |
+---------+
|Id (PK) |
|IsActive |
|... |
|.. |
|. |
+---------+
+--------------------+
|Resume_Translation |
+--------------------+
|ResumeId (PK, FK) |
|Language (PK) |
|Title |
|Description |
|... |
|.. |
|. |
+--------------------+
所以我可以拥有带有两个连接表的数据:
+----------------------------------------------------------+
|Id | IsActive | ResumeId | Language | Title | Description |
+----------------------------------------------------------+
|1 | true | 1 | 'fr' | 'One' | 'One desc' |
|1 | true | 1 | 'pl' | 'Raz' | 'Raz Opis' |
|2 | true | 2 | 'fr' | 'B' | 'bla bla' |
|3 | true | 3 | 'fr' | 'C' | 'C bla bla' |
+----------------------------------------------------------+
从我的域角度来看,我只关心 Resume
实体。我不想拥有 Resume
实体及其 Resume_Translations
集合,因为我只有一个具有当前翻译的 Resume
实体。
public class Resume
{
public virtual int Id{ get; protected internal set; }
public virtual string Language { get; protected internal set; }
public virtual string Title { get; protected internal set; }
public virtual string Description { get; protected internal set; }
public virtual bool IsActive { get; protected internal set; }
}
我当前使用 Fluent NHibernate 的映射如下:
public class ResumeMap : ClassMap<Resume>
{
public ResumeMap()
{
Table("Resume");
Id(x => x.Id);
Map(x => x.IsActive);
// other properties
Join("Resume_Translation", m =>
{
m.Fetch.Join();
m.Map(x => x.Language).Length(5);
m.Map(x => x.Title).Length(100);
m.Map(x => x.Description).Length(200);
});
}
}
我可以毫无问题地从存储库中获取我想要的内容,只需传入 WHERE 谓词、Resume 的 Id 和我想要的语言即可。
但是,我在插入和更新值时遇到一些问题。
我的问题是:我如何定义 NHibernate 仅在 Resume_Translation 表中插入新记录而不是更新当前实体的记录的映射?
所以我想要实现的是如果我在数据库中有以下记录:
|2 | true | 2 | 'fr' | 'B' | 'bla bla' |
Join 对于表之间的一对一关系很有用,因此如果我将其放入我的实体中并更改语言和翻译,nhibernate 正在执行更新,我可以理解它。如果我尝试通过不同的语言和翻译添加具有相同 ID 的新实体,nhibernate 会产生一个错误,表明密钥已存在,我也理解它。
所以,我肯定走错了路,但如果有人能指出我如何实现我想要的映射的正确解决方案,我将不胜感激。
另一个问题,从业务角度来看,您如何处理实体及其翻译?
预先感谢您的帮助。
托马斯
I have the following data structure :
+---------+
|Resume |
+---------+
|Id (PK) |
|IsActive |
|... |
|.. |
|. |
+---------+
+--------------------+
|Resume_Translation |
+--------------------+
|ResumeId (PK, FK) |
|Language (PK) |
|Title |
|Description |
|... |
|.. |
|. |
+--------------------+
So I could have such a data with two joined tables :
+----------------------------------------------------------+
|Id | IsActive | ResumeId | Language | Title | Description |
+----------------------------------------------------------+
|1 | true | 1 | 'fr' | 'One' | 'One desc' |
|1 | true | 1 | 'pl' | 'Raz' | 'Raz Opis' |
|2 | true | 2 | 'fr' | 'B' | 'bla bla' |
|3 | true | 3 | 'fr' | 'C' | 'C bla bla' |
+----------------------------------------------------------+
From my domain point of view I care only about Resume
entity. I don't want to have Resume
entity with its collection of Resume_Translations
because I would only have one Resume
entity with a current translation.
public class Resume
{
public virtual int Id{ get; protected internal set; }
public virtual string Language { get; protected internal set; }
public virtual string Title { get; protected internal set; }
public virtual string Description { get; protected internal set; }
public virtual bool IsActive { get; protected internal set; }
}
My current mapping with Fluent NHibernate is as follows :
public class ResumeMap : ClassMap<Resume>
{
public ResumeMap()
{
Table("Resume");
Id(x => x.Id);
Map(x => x.IsActive);
// other properties
Join("Resume_Translation", m =>
{
m.Fetch.Join();
m.Map(x => x.Language).Length(5);
m.Map(x => x.Title).Length(100);
m.Map(x => x.Description).Length(200);
});
}
}
I can get what I want from the repository without problem just passing in the WHERE predicate the Id of Resume and the Language I want to.
However I have some problems with Inserting and Updating the values.
My question is: How I would define a mapping that NHibernate Inserts a new record only in Resume_Translation table instead of Updating the record for the current entity ?
So what I want to achieve is if I have in the database the following record :
|2 | true | 2 | 'fr' | 'B' | 'bla bla' |
Join is good for one to one relationship between tables so if I get this into my entity and I change the language and translation, nhibernate is performing an update and I can understand it. If I try to add a new entity with the same Id by different language and translation, nhibernate yields an error that a key already exists and I understand it also.
So, certainly I'm going down the wrong path, but If some one could point me to the correct solution on how I could achieve a mapping that I want I would greatly appreciate.
Another question, how do you deal with a entities and theirs translations from the business point of view ?
Thanks, in advance for your help.
Thomas
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
斯特凡走在正确的道路上。我已经调整了他的建议,建立一个双向关联,这将使更新变得更加容易。这种方法的一个问题是,您需要在插入时手动分配 ResumeTranslation 实例的 Resume 属性,以便 NHibernate 正确地将 Resume 表键分配给 ResumeTranslation 行。因此,考虑到您正在映射的关联,它在 Fluent NH 中的外观如下:
Stefan is on the right track. I've tweaked his suggestion to have a bi-directional association which would make updating a lot easier. One catch with this approach is that you need to manually assign the Resume property of the ResumeTranslation instance when inserting so that NHibernate will properly assign the Resume table key to the ResumeTranslation row. So, given the associations you are mapping, this is how it would look in Fluent NH:
对我来说似乎是一对多的关系。我个人会在我的 Resume 对象中拥有一个 ResumeTranslation 对象的集合。然后我会将其映射为标准的一对多。
然后,您可以向代表您的
当前翻译
的Resume实体添加另一个属性ActiveResumeTranslation。Seems like a one to many relationship to me. I would personally have a collection of ResumeTranslation objects within my Resume object. I would then map this as a standard one to many.
You could then add another property ActiveResumeTranslation to your Resume entity that is representative of your
current translation
.使用字典,使用语言作为键怎么样?
并将其相应地映射为带有复合元素的
map
(抱歉,我没有使用 Fluent,所以不要问我它会是什么样子)。它将与您的数据库模型完全匹配。What about using a dictionary, using the language as a key?
And map it accordingly as a
map
with a composite-element (sorry, I'm not using fluent, so don't ask me how it would look like). It would exactly match your database model.