我已经阅读了很多关于同样错误的问题,但没有找到与我的确切问题相符的问题。我试图使用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;}
这样做的正确方法是什么?
答案 0 :(得分:28)
您必须将QueryOver查询视为(几乎)直接转换为SQL。考虑到这一点,想象一下这个SQL查询:
select
Album.*
from
Album
where
Album.Name = 'SomeAlbumName' and
Album.Artist.Name = 'SomeArtistName'
这不起作用,因为您无法在SQL语句中访问相关表的属性。您需要创建从Album
到Artist
的连接,然后然后使用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);
}
}
解决了错误。