Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fluent nhibernate HasOne WithForeignKey not working

Tags:

Whenever I load a Task class, the Document property is always null, despite there being data in the db.

Task class:

public class Task {     public virtual Document Document { get; set; } 

Task Mapping override for AutoPersistenceModel:

public void Override(AutoMap<Task> mapping) {     mapping.HasOne(x => x.Document)         .WithForeignKey("Task_Id"); 

As you can see form what NHProf says is being run, the join condition is wrong, the WithForeignKey doesnt seem to take effect. In fact, i can write any string in the above code and it makes no difference.

FROM   [Task] this_     left outer join [Document] document2_     on this_.Id = document2_.Id 

It should be:

FROM   [Task] this_     left outer join [Document] document2_     on this_.Id = document2_.Task_Id 

If i hack the data in the db so that the ids match, then data is loaded, but obviously this is incorrect - but at least it proves it loads data.

Edit: rummaging in the fluent nhib source to find the XML produces this:

<one-to-one foreign-key="Task_Id" cascade="all" name="Document" class="MyProject.Document, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />  

Edit: heres the schema:

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, 

Anyone got any ideas?

Thanks

Andrew

like image 239
Andrew Bullock Avatar asked Mar 13 '09 16:03

Andrew Bullock


People also ask

What is the difference between NHibernate and fluent NHibernate?

Fluent NHibernate offers an alternative to NHibernate's standard XML mapping files. Rather than writing XML documents, you write mappings in strongly typed C# code. This allows for easy refactoring, improved readability and more concise code.


2 Answers

I ran into the same issue today. I believe the trick is not to use .ForeignKey(...) with the .HasOne mapping, but to use .PropertyRef(...) instead. The following is how I define a One-to-one relationship between an Organisation (Parent) and its Admin (Child):

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

The Admin has a simple reference to the Organisation using its Foreign Key:

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

When retrieving an Organisation, this will load up the correct Admin record, and properly cascades updates and deletes.

like image 141
PLN Avatar answered Sep 30 '22 14:09

PLN


You should use:

References(x => x.Document, "DocumentIdColumnOnTask")

like image 37
eulerfx Avatar answered Sep 30 '22 15:09

eulerfx