流利的NHibernate"无法解决财产问题"

时间:2014-12-17 14:06:35

标签: c# nhibernate fluent-nhibernate queryover

我已经阅读了很多关于同样错误的问题,但没有找到与我的确切问题相符的问题。我试图使用Fluent NHibernate来访问对象的属性,它本身就是根对象的一部分。一些答案说我需要使用投影,其他我需要使用连接,我认为它应该通过延迟加载。

以下是我的两个课程以及Fluent映射:

艺术家班级

public class Artist
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Album> Albums { get; set; }
    public virtual string MusicBrainzId { get; set; }
    public virtual string TheAudioDbId { get; set; }

    public Artist() { }
}

public class ArtistMap : ClassMap<Artist>
{
    public ArtistMap()
    {
        LazyLoad();
        Id(a => a.Id);
        Map(a => a.Name).Index("Name");
        HasMany(a => a.Albums)
            .Cascade.All();
        Map(a => a.MusicBrainzId);
        Map(a => a.TheAudioDbId);
    }
}

专辑类

public class Album
{
    public virtual int Id { get; set; }
    public virtual Artist Artist { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Track> Tracks { get; set; }
    public virtual DateTime ReleaseDate { get; set; }
    public virtual string TheAudioDbId { get; set; }
    public virtual string MusicBrainzId { get; set; }

    public Album() { }
}

public class AlbumMap : ClassMap<Album>
{
    public AlbumMap()
    {
        LazyLoad();
        Id(a => a.Id);
        References(a => a.Artist)
            .Cascade.All();
        Map(a => a.Name).Index("Name");
        HasMany(a => a.Tracks)
            .Cascade.All();
        Map(a => a.ReleaseDate);
        Map(a => a.TheAudioDbId);
        Map(a => a.MusicBrainzId);
    }
}

解释此代码时会发生错误:

var riAlbum = session.QueryOver<Album>()
                .Where(x => x.Name == albumName && x.Artist.Name == artist)
                .List().FirstOrDefault();

当Fluent NHibernate尝试解析x.Artist.Name值时发生错误:

  

{&#34;无法解析属性:Artist.Name of:Album&#34;}

这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:28)

您必须将QueryOver查询视为(几乎)直接转换为SQL。考虑到这一点,想象一下这个SQL查询:

select
    Album.*
from
    Album
where
    Album.Name = 'SomeAlbumName' and
    Album.Artist.Name = 'SomeArtistName'

这不起作用,因为您无法在SQL语句中访问相关表的属性。您需要创建从AlbumArtist的连接,然后然后使用Where子句:

var riAlbum = 
    session.QueryOver<Album>()
               .Where(al => al.Name == albumName)
           .JoinQueryOver(al => al.Artist)
               .Where(ar => ar.Name == artistName)
           .List()
           .FirstOrDefault();

此外,由于您使用的是FirstOrDefault,因此您可能需要考虑将该逻辑移至数据库端。目前,您正在撤回符合条件的每条记录,然后选择第一条记录。您可以使用.Take将查询限制为1个结果:

var riAlbum = 
    session.QueryOver<Album>()
               .Where(al => al.Name == albumName)
           .JoinQueryOver(al => al.Artist)
               .Where(ar => ar.Name == artistName)
           .Take(1)
           .SingleOrDefault<Album>();

答案 1 :(得分:1)

另一种解释是您缺少NHibernateClassMapping定义中此属性或字段的映射。我来到这里是为什么我会根据以下情况得出此错误。

 var query = scheduleRepository.CurrentSession().Query<Schedule>()
                .Where(x => x.ScheduleInfo.StartDate.Date < dateOfRun.Date);

这给了我一个StartDate的无法解决属性错误。这是一个令人头疼的问题,因为我一直都在使用这种语法。

我的映射文件如下:

public class ScheduleInfoMapping : NHibernateClassMapping<ScheduleInfo>
    {
        public ScheduleInfoMapping()
        {
            DiscriminateSubClassesOnColumn("Type");
            Map(x => x.Detail).MapAsLongText();
        }
    }

缺少StartDate。改为:

public class ScheduleInfoMapping : NHibernateClassMapping<ScheduleInfo>
    {
        public ScheduleInfoMapping()
        {
            DiscriminateSubClassesOnColumn("Type");
            Map(x => x.Detail).MapAsLongText();
            Map(x => x.StartDate);
        }
    }

解决了错误。