流利的nhibernate HasOne WithForeignKey无法正常工作

时间:2009-03-13 16:54:48

标签: fluent-nhibernate

每当我加载Task类时,尽管db中有数据,Document属性始终为null。

任务类:

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,

有人有任何想法吗?

由于

安德鲁

6 个答案:

答案 0 :(得分:93)

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

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

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

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

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

答案 1 :(得分:6)

您应该使用:

参考文献(x =&gt; x.Document,“DocumentIdColumnOnTask”)

答案 2 :(得分:5)

我认为这里的问题是“HasOne”惯例意味着你指的是另一件事(标准的关系方式,说“多对一”/“一对一”);通过在文档上放置一个Task_ID,实际关系是一个HasMany,但你有一种隐含的理解,即每个任务只有一个文档。

抱歉 - 我不知道如何解决这个问题,但我会对看到解决方案的内容感兴趣(我不使用NHibernate或Fluent NHibernate,但我一直在研究它以便将来使用)。解决方案(来自非常少见的人)将使Document成为Task上的集合,然后提供Document属性,该属性返回集合中的第一个(使用隐藏Documents属性的接口,因此没有人认为他们可以添加它的新项目。)

查看文档并考虑eulerfx的答案,也许这种方法可能是:

References(x => x.Document)
    .TheColumnNameIs("ID")
    .PropertyRef(d => d.Task_ID);

编辑:这样这个答案有适当的解决方案:正确的路径是更新数据库模式以匹配代码的意图。这意味着将DocumentID添加到Task表中,因此Task和Document之间存在多对一关系。如果无法进行架构更改,则References()将是适当的解决方案。

答案 3 :(得分:2)

我尝试过这个解决方案:

仅在文档中:

mapping.HasOne(x => x.Task).ForeignKey("Task_ID").Constrained().Cascade.All();

答案 4 :(得分:0)

正如eulerfx指出的那样,

  

表格结构表明任务可能有多个文件

和克里斯说:

  

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

这当然是正确的,所以我已将其撤销,因此Task有一个可以为空的Document_Id。

感谢你们俩的帮助!

我为接受的答案翻了一个硬币,如果我能打勾我会的!

答案 5 :(得分: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();           
    }
}