流利的休眠 HasOne WithForeignKey 不起作用
Posted
技术标签:
【中文标题】流利的休眠 HasOne WithForeignKey 不起作用【英文标题】:fluent nhibernate HasOne WithForeignKey not working 【发布时间】:2010-10-13 05:17:33 【问题描述】:每当我加载一个 Task 类时,Document 属性始终为 null,尽管 db 中有数据。
任务类:
public class Task
public virtual Document Document get; set;
AutoPersistenceModel 的任务映射覆盖:
public void Override(AutoMap<Task> mapping)
mapping.HasOne(x => x.Document)
.WithForeignKey("Task_Id");
正如您所见,NHProf 所说的正在运行,连接条件错误,WithForeignKey 似乎没有生效。事实上,我可以在上面的代码中写任何字符串,它没有任何区别。
FROM [Task] this_
left outer join [Document] document2_
on this_.Id = document2_.Id
应该是:
FROM [Task] this_
left outer join [Document] document2_
on this_.Id = document2_.Task_Id
如果我破解数据库中的数据以使 ids 匹配,则加载数据,但显然这是不正确的 - 但至少它证明它加载了数据。
编辑:在流畅的 nhib 源中翻找 XML 会产生这样的结果:
<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
编辑:这是架构:
CREATE TABLE [dbo].[Document](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Task_Id] [int] NOT NULL,
CREATE TABLE [dbo].[Task](
[Id] [int] IDENTITY(1,1) NOT NULL,
有人有什么想法吗?
谢谢
安德鲁
【问题讨论】:
【参考方案1】:我试过这个解决方案:
就在文档中:
mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();
【讨论】:
【参考方案2】:我一直在为同样的 Has One 问题苦苦挣扎,终于发现这行得通:
public class ParentMap : ClassMap<Parent>
public ParentMap()
Id(x => x.Id);
HasOne(s => s.Child).Cascade.All();
public class ChildMap : ClassMap<Model.Child>
public ChildMap()
Id(x => x.Id);
HasOne(s => s.Parent).Constrained().ForeignKey();
【讨论】:
两个表中的compositeid怎么办?【参考方案3】:我今天遇到了同样的问题。我相信诀窍不是将 .ForeignKey(...) 与 .HasOne 映射一起使用,而是使用 .PropertyRef(...) 。以下是我如何定义组织(父)与其管理员(子)之间的一对一关系:
HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All();
管理员使用其外键对组织进行简单引用:
References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable();
在检索组织时,这将加载正确的管理员记录,并正确地级联更新和删除。
【讨论】:
似乎完美的答案是这个和 Chris Shaffer 的答案的结合。这个答案提供了一个使用 Fluent NHibernate 的工作实现,而 Chris Shaffer 提供了一些关于为什么初始实现不起作用的“理论”。 也为我工作,非常感谢。但是 HasOne().ForeignKey() 是什么? +1 但我必须将引用写为 References(x => x.Organisation).ForeignKey("ORAD_FK_ORGANISATION").Not.Nullable();因为它将外键名称作为组织的列名【参考方案4】:我认为这里的问题是“HasOne”约定意味着您指向另一件事(说“多对一”/“一对一”的标准关系方式);通过将 Task_ID 放在文档上,实际关系是 HasMany,但您有某种隐含的理解,即每个任务只会有一个文档。
抱歉 - 我不知道如何解决这个问题,但我有兴趣了解解决方案是什么(我不使用 NHibernate 或 Fluent NHibernate,但我一直在研究它以供将来使用)。一个解决方案(来自一个几乎没有想法的人)是让 Documents 成为 Task 上的一个集合,然后提供一个 Document 属性,该属性返回集合中的第一个(使用隐藏 Documents 属性的界面,因此没有人认为他们可以添加新项目)。
查看文档并考虑 eulerfx 的答案,也许方法类似于:
References(x => x.Document)
.TheColumnNameIs("ID")
.PropertyRef(d => d.Task_ID);
编辑:这个答案有适当的解决方案:正确的路径是更新数据库模式以匹配代码的意图。这意味着将 DocumentID 添加到 Task 表中,因此 Task 和 Document 之间存在多对一的关系。如果无法更改架构,References() 将是合适的解决方案。
【讨论】:
我同意这种可能性,但为什么 Task_Id 没有在任何地方呈现? (即使它是错误的,因此会导致异常 - 但它不会) 这确实有效,但这意味着我需要 Document 上的 Task_id 属性,我宁愿没有。虽然现在可以工作,但谢谢【参考方案5】:正如 eulerfx 指出的那样,
表格结构表明一个任务可能有多个文档
克里斯说:
通过将 Task_ID 放在文档上,实际关系是 HasMany,但您有某种隐含的理解,即每个任务只有一个文档。
这当然是正确的,所以我把它反转了,所以 Task 有一个可为空的 Document_Id。
感谢两位的帮助!
我投了一枚硬币以获得接受的答案,如果我能同时勾选我会的!
【讨论】:
嘿,安德鲁,PLN 的答案是肯定的。我会说,通过重新做数据库,你实际上做了正确的事情。但有时您无法更改数据库,而这正是 Fluent Mappings 真正大放异彩的地方。 HasOne 就是这样一个功能,你和我都错误地使用了它。 PLN 指出了使用它的正确方法......我的 2 美分【参考方案6】:你应该使用:
参考(x => x.Document, "DocumentIdColumnOnTask")
【讨论】:
tblDocument 有 Task_Id,而不是 tblTask 有 Document_Id 哦,好吧,错过了那部分。然后我想在任务表上有一个 docID 是最有意义的。否则表结构表明一个任务可能有多个文档。 是的,我想是的。这是有原因的,但我不记得为什么。我会考虑并考虑扭转它。 ta以上是关于流利的休眠 HasOne WithForeignKey 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
nhibernate中的HasOne和References有啥区别?
Laravel 中 BelongsTo 和 HasOne 有啥区别
HasOne 和 HasMany 用于同一张表 cakephp