nHibernate一对一属性在加载时为null

时间:2014-01-07 11:30:10

标签: nhibernate fluent-nhibernate nhibernate-mapping fluent-nhibernate-mapping

我在TimeRecord和Location之间有一对一的关系。 此实现与文档中描述的完全相同: 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();


    }
}

现在我使用以下方法查询我的TimeRecords:

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

Unfortunalelty我的Location对象始终为null,即使Location表中有相应的条目,但当我使用所需的TimeRecordId查询相应的Location时,它也会正确返回。

请参阅此处的代码(代码位于循环内部 - &gt; trCurrent是从“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
                }

我的LocationRepository方法的实现:

  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();
        }
    }

有人可以告诉我为什么我的位置没有得到正确解决吗?

干杯, 斯蒂芬

1 个答案:

答案 0 :(得分:0)

人们声称

  

HasOne / one-to-one通常用于特殊情况。通常,在大多数情况下,您使用References / many-to-one关系(请参阅:I think you mean a many-to-one)。如果您确实想要一对一,那么您可以使用HasOne方法。

如果你确实想要一对一并使用它,你应该记住默认情况下实体是由它们的ID连接的。

如果您检查生成的SQL,您会看到类似JOIN Location ON Location.Id = TimeRecord.Id的内容。

为了获得像JOIN Location ON Location.TimeRecordId = TimeRecord.Id这样的SQL,您应该通过PropertyRef()方法指定外键。因此,您的映射可能是以下内容:

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();        
    }
}

为了确保所有地点都有TimeRecord,您可以将.Not.Nullable()添加到LocationMap课程中。