23

每当我加载 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

如果我破解数据库中的数据以使 id 匹配,则加载数据,但显然这是不正确的 - 但至少它证明它加载了数据。

编辑:在流利的 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,

有人有什么想法吗?

谢谢

安德鲁

4

6 回答 6

94

我今天遇到了同样的问题。我相信诀窍不是将 .ForeignKey(...) 与 .HasOne 映射一起使用,而是使用 .PropertyRef(...) 。以下是我如何定义组织(父)与其管理员(子)之间的一对一关系:

HasOne(x => x.Admin).PropertyRef(r => r.Organisation).Cascade.All();

管理员使用其外键对组织进行了简单的引用:

References(x => x.Organisation, "ORAD_FK_ORGANISATION").Not.Nullable();

检索组织时,这将加载正确的管理员记录,并正确级联更新和删除。

于 2010-03-05T11:42:42.037 回答
6

你应该使用:

参考文献(x => x.Document,“DocumentIdColumnOnTask”)

于 2009-03-13T17:10:27.770 回答
5

我认为这里的问题是“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() 将是适当的解决方案。

于 2009-03-13T17:09:33.047 回答
2

我试过这个解决方案:

就在文档中:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();
于 2012-03-27T06:39:22.493 回答
0

正如 eulerfx 指出的那样,

表结构表明一个任务可能有多个文档

克里斯说:

通过将 Task_ID 放在文档上,实际关系是 HasMany,但您有某种隐含的理解,即每个任务只有一个文档。

这当然是正确的,因此我将其反转,因此 Task 具有可为空的 Document_Id。

感谢两位的帮助!

我为接受的答案掷了一枚硬币,如果我能同时勾选两个我会的!

于 2009-03-13T17:40:03.737 回答
0

我一直在努力解决同样的 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();           
    }
}
于 2011-12-30T10:33:39.577 回答