0

I have a One to One relation between a TimeRecord and the Location. This implementation is exactly the same es described in documentation: https://github.com/jagregory/fluent-nhibernate/wiki/Fluent-mapping

 public class TimeRecordMap : ClassMap<TimeRecord>
{
    public TimeRecordMap()
    {
        Id(x => x.Id);

        Map(x => x.Description);
        Map(x => x.StartTime);
        Map(x => x.EndTime);


        HasOne(x => x.Location).Cascade.All();

    }
}

   public class LocationMap : ClassMap<Location>
{
    public LocationMap()
    {
        Id(x => x.Id);

        Map(x => x.Longitude);
        Map(x => x.Latitude);
        Map(x => x.Adress);

        References(x => x.TimeRecord).Unique();


    }
}

Now I query my TimeRecords with the following method:

  public IList<TimeRecord> GetTimeRecords(string userid)
    {
        var query = Session.Query<TimeRecord>().Where(tr => tr.User.Id == userid);
        return query.ToList();
    }

Unfortunalelty my Location object is always null even if there is a coresponding entry in Location table but when I query for the coresponding Location with the desired TimeRecordId it is returned correctly.

See code here (code is inside a loop -> trCurrent is the current object in list received from "GetTimeRecords")

  Location location = _locationRepo.getLocationByTimeRecordId(trCurrent.Id);
                //trCurrent.Location = location; <- don't want to do it that way
                if (trCurrent.Location != null)<- always null
                {
                       ... do stuff here
                }

Implementation of my LocationRepository method:

  public Location getLocationByTimeRecordId(int timeId)
    {
        var query = Session.Query<Location>()
                    .Where(tr => tr.TimeRecord.Id == timeId && tr.IsDeleted == false);

        List<Location> lstReturn = query.ToList();
        if (lstReturn.Count() == 0)
        {
            return null;
        }
        else
        {
            return lstReturn.First();
        }
    }

Can someone tell me why my Location is not resolved corretly?

Cheers, Stefan

stefan
  • 1,336
  • 3
  • 21
  • 46

1 Answers1

0

People claim that

HasOne / one-to-one is usually reserved for a special case. Generally, you'd use a References / many-to-one relationship in most situations (see: I think you mean a many-to-one). If you really do want a one-to-one, then you can use the HasOne method.

If you really do want a one-to-one and use it, you should remember that entities are joined by their ids by default.

If you check generated SQL you'll see something like JOIN Location ON Location.Id = TimeRecord.Id.

In order to get SQL like JOIN Location ON Location.TimeRecordId = TimeRecord.Id you should specify the foreign key via PropertyRef() method. So your mapping could be the folloving:

public class TimeRecordMap : ClassMap<TimeRecord>
{
    public TimeRecordMap()
    {
        Id(x => x.Id);

        Map(x => x.Description);
        Map(x => x.StartTime);
        Map(x => x.EndTime);

        HasOne(x => x.Location).Cascade.All().PropertyRef(it => it.TimeRecord);
    }
}

public class LocationMap : ClassMap<Location>
{
    public LocationMap()
    {
        Id(x => x.Id);

        Map(x => x.Longitude);
        Map(x => x.Latitude);
        Map(x => x.Adress);

        References(x => x.TimeRecord/*, "TimeRecordId"*/).Unique().Not.Nullable();        
    }
}

In order to make sure that any location has TimeRecord you can add .Not.Nullable() into your LocationMap class.

James Wiseman
  • 29,946
  • 17
  • 95
  • 158
Ilya Palkin
  • 14,687
  • 2
  • 23
  • 36
  • I tried it with ".PropertyRef()" as described in the sample( "HasOne( x => x.SteeringWheel ).PropertyRef( x => x.SteeringWheel );" ) but this gave me a compiler error. However, it seems you are doing this corretly, no comepile error with your code. And why do people claim that? What would be the alternative? Not all of my TimeRecord's have locations attached to it. – stefan Jan 09 '14 at 08:08
  • It is simply the quote from project's wiki. I do use one-to-one. You are right that example from wiki could not be compiled. If your locations can be without `TimeRecord`, you should remove `.Not.Nullable()` from my example. It will be even easier. – Ilya Palkin Jan 09 '14 at 10:27
  • My Location can't live without TimeRecord. Many thanks for assistance!! – stefan Jan 09 '14 at 11:30
  • This yields PropertyValueException: "not-null property references a null or transient value (...)" when trying to save a new instance of `TimeRecordMap` with the cascade set to "All". I would probably have to explicitly save the `LocationMap` always before `TimeRecordMap` which make the cascade option useless. – Mateusz Myślak Apr 24 '19 at 07:17