Свободный NHibernate "Не удалось разрешить свойство"

Я прочитал много вопросов об этой же ошибке, но ни один из них не соответствует моей точной проблеме. Я пытаюсь получить доступ к свойству объекта, самой части корневого объекта, используя 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:

{ "не удалось разрешить свойство: Artist.Name of: Album" }

Каким будет правильный способ сделать это?

Ответ 1

Вы должны думать о своем запросе 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>();