首页 文章

流利的NHibernate“无法解决 property 问题”

提问于
浏览
14

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

这是我的两个类以及Fluent映射:

Artist class

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

Album class

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值时,会发生错误:

{“无法解析属性:Artist.Name of:Album”}

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

2 回答

  • 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

    另一种解释是您缺少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);
            }
        }
    

    哪解决了这个错误 .

相关问题