J'ai lu beaucoup de questions sur cette même erreur mais aucune depuis pour correspondre à mon problème exact. J'essaie d'accéder à la propriété d'un objet, lui-même faisant partie d'un objet racine, à l'aide de Fluent NHibernate. Certaines réponses disent que je dois utiliser des projections, d’autres que j’ai besoin d’utiliser join, et je pense que cela devrait fonctionner par chargement paresseux.
Voici mes deux classes avec les mappages Fluent:
Cours d'artiste
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);
}
}
Classe d'album
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);
}
}
Et l'erreur se produit lorsque ce code est interprété:
var riAlbum = session.QueryOver<Album>()
.Where(x => x.Name == albumName && x.Artist.Name == artist)
.List().FirstOrDefault();
L'erreur se produit lorsque NHibernate Fluent tente de résoudre la valeur x.Artist.Name:
{"Impossible de résoudre la propriété: Artist.Name of: Album"}
Quelle serait la bonne façon de faire cela?
Vous devez considérer votre requête QueryOver comme une traduction (presque) directe en SQL. Dans cet esprit, imaginez cette requête SQL:
select
Album.*
from
Album
where
Album.Name = 'SomeAlbumName' and
Album.Artist.Name = 'SomeArtistName'
Cela ne fonctionnera pas car vous ne pouvez pas accéder aux propriétés d'une table liée comme celle-ci dans une instruction SQL. Vous devez créer une jointure de Album
à Artist
et then use une clause Where
:
var riAlbum =
session.QueryOver<Album>()
.Where(al => al.Name == albumName)
.JoinQueryOver(al => al.Artist)
.Where(ar => ar.Name == artistName)
.List()
.FirstOrDefault();
De même, puisque vous utilisez FirstOrDefault
, vous pouvez envisager de déplacer cette logique vers la fin de la base de données. Actuellement, vous retirez tous les enregistrements correspondant à vos critères, puis vous prenez le premier. Vous pouvez utiliser .Take
pour limiter la requête à 1 résultat:
var riAlbum =
session.QueryOver<Album>()
.Where(al => al.Name == albumName)
.JoinQueryOver(al => al.Artist)
.Where(ar => ar.Name == artistName)
.Take(1)
.SingleOrDefault<Album>();
Une autre explication est qu'il vous manque le mappage de cette propriété ou de ce champ dans une définition NHibernateClassMapping. Je suis venu ici pour expliquer pourquoi je recevais cette erreur en fonction du scénario suivant.
var query = scheduleRepository.CurrentSession().Query<Schedule>()
.Where(x => x.ScheduleInfo.StartDate.Date < dateOfRun.Date);
Cela me donnait une erreur Impossible de résoudre la propriété pour StartDate. C'était un scratcher de tête, puisque j'utilise cette syntaxe tout le temps.
Mon fichier de mapping était le suivant:
public class ScheduleInfoMapping : NHibernateClassMapping<ScheduleInfo>
{
public ScheduleInfoMapping()
{
DiscriminateSubClassesOnColumn("Type");
Map(x => x.Detail).MapAsLongText();
}
}
qui manquait la StartDate. Changé en:
public class ScheduleInfoMapping : NHibernateClassMapping<ScheduleInfo>
{
public ScheduleInfoMapping()
{
DiscriminateSubClassesOnColumn("Type");
Map(x => x.Detail).MapAsLongText();
Map(x => x.StartDate);
}
}
Ce qui a résolu l'erreur.