0
votes

I have a one-to-one relationship in my db and I seem to be having issues with my fluent nhibernate mapping of this relationship.

When I attempt to insert a new TableA entity I receive the following error: "unable to resolve property: TableA". The error is thrown on this line in the repository: int id = (int)_session.Save(item);

Repository code:

public T Save(T item)
{
    try
    {
        _session.BeginTransaction();
        int id = (int)_session.Save(item);
        _session.Transaction.Commit();
        return _session.Get<T>(id);
    }
    catch (Exception)
    {
        _session.Transaction.Rollback();
        throw;
    }
}

Table definitions:

Table A

Id (int, pk, identity) 
Field1 (nvarchar) 
Field2 (date) 
...

Table B

TableAId (int, pk) <-- no fk constraint on these tables
Field1 (nvarchar)
Field2 (nvarchar)
Field3 (bit)

Classes:

public class TableA
{
    public virtual int Id {get;set;}
    public virtual string Field1 {get;set;}
    public virtual DateTime Field2 {get;set;}
    public virtual TableB TableB {get;set;}
}

public class TableB
{
    public virtual int TableAId {get;set;}
    public virtual string Field1 {get;set;}
    public virtual string Field2 {get;set;}
}

Mapping:

public class TableAMap : ClassMap<TableA>
{
    public TableAMap(){
        Id(x => x.Id);
        Map(x => x.Field1);
        Map(x => x.Field2);
        HasOne(x => x.TableB)
         .Cascade.SaveUpdate()
         .Fetch.Join();
    }
}

public class TableBMap : ClassMap<TableB>
{
    public TableBMap()
    {
        Id(x => x.Id, "TableAId").GeneratedBy.Foreign("TableA");
        Map(x => x.Field1);
        Map(x => x.Field2);
        Map(x => x.Field3);
    }
}

I used these as a reference: http://avinashsing.sunkur.com/2011/09/29/how-to-do-a-one-to-one-mapping-in-fluent-nhibernate/

One-to-one Mapping issue with NHibernate/Fluent: Foreign Key not updateing

IndexOutOfRangeException Deep in the bowels of NHibernate

I've been looking at this for so long now I fear I'm missing something simple (and stupid).


Update: Tried this:

public class TableA
{
    public virtual int Id {get;set;}
    public virtual string Field1 {get;set;}
    public virtual DateTime Field2 {get;set;}
    public virtual TableB TableB {get;set;}
    public virtual int TableBId
    {
         get{return TableB.Id;}
         set{}
    }
}

public class TableAMap : ClassMap<TableA>
{
    public TableAMap()
    {
        Id(x => x.Id);
        Map(x => x.Field1);
        Map(x => x.Field2);
        HasOne<TableB>(x => x.TableB)
         .Cascade.SaveUpdate()
         .Fetch.Join()
         .ForeignKey("TableBId");
    }
}

public class TableBMap : ClassMap<TableB>
{
    public TableBMap()
    {
        Id(x => x.Id, "TableAId");
        Map(x => x.Field1);
        Map(x => x.Field2);
        Map(x => x.Field3);
    }
}

I didn't get the "unable to resolve property: TableA" error this time, but I received a different error. It seems like the Id of the TableA record did not cascade to the TableB record.


Did some more reading.
Found this post: fluent NHibernate one-to-one relationship?

Made some more changes:

public class TableAMap : ClassMap<TableA>
{
    public TableAMap()
    {
        Id(x => x.Id);
        Map(x => x.Field1);
        Map(x => x.Field2);
        HasOne<TableB>(x => x.TableB)
         .Cascade.All()
         .Constrained()
         .Fetch.Join()
         .ForeignKey("TableBId");
    }
}

public class TableBMap : ClassMap<TableB>
{
    public TableBMap()
    {
        Id(x => x.Id, "TableAId").UnsavedValue(0).GeneratedBy.Foreign("TableA");
        Map(x => x.Field1);
        Map(x => x.Field2);
        Map(x => x.Field3);
        HasOne<TableA>(x => x.TableA);
    }
}

New error: "attempted to assign id from null one-to-one property: TableA"

1
Are you positive it's one-to-one in the nhibernate world? This link might help.Jay Otterbein
Yes, I read that article two days ago. This would be a one to one because the two tables share a mutually exclusive primary key. There is no direct reference between TableA and TableB. See the one-to-one example here, it is just like the design I'm working with.CDR12

1 Answers

0
votes

Even though this relationship is a one-to-one, and should be a one-to-one, I ended up modifying my database defintion to make this relationship a many-to-one and I mapped it as a many-to-one. Now it works. I'm not happy about it though, I think there should be a way to successfully map a one-to-one.

I was wasting too much time trying to get the one-to-one mapping to work and for the sake of my timeline I just needed to move on.