2010-12-13 4 views
3

Fluent nHibernate utilisant nHibernate v. 2.1.2.4, nHibernate.Linq v. 1.1.0.1001 et Fluent NHibernate v. 1.1.0.685.LINQ to NHibernate: impossible de résoudre la propriété

J'ai un objet de domaine avec un champ DateTime appelé DateOfEvent. Ceci est un champ date/heure réel dans la base de données. J'ai également ajouté 2 nouvelles propriétés YearOfEvent qui saisit l'année à partir du champ DateOfEvent ainsi que MontOfEvent qui récupère le mois à partir du champ DateOfEvent.

public class Event 
{ 
    public Event() { } 
    public virtual Int32 Id { get; set; } 
    public virtual String Title { get; set; } 
    public virtual DateTime DateOfEvent { get; set; } 
    public virtual Int32 YearOfEvent 
    { 
     get { return DateOfEvent.Year; } 
    } 
    public virtual Int32 MonthOfEvent 
    { 
     get { return DateOfEvent.Month; } 
    } 
    public virtual String Location { get; set; } 
    public virtual String City { get; set; } 
    public virtual String State { get; set; } 
    public virtual String Zip { get; set; } 
    public virtual String Description { get; set; } 
    public virtual Boolean HasImage { get; set; } 
    public virtual Boolean IsActive { get; set; } 
} 

Cependant, lors de l'exécution de cette méthode:

public IList<Event> GetActiveEvents(int pageNumber, int pageSize, out int totalItems) 
    { 
     Int32 skip = Misc.NumberToSkip(pageNumber, pageSize); 
     totalItems = (from e in _session.Linq<Event>() 
         where e.IsActive 
         select e).Count(); 

     return (from e in _session.Linq<Event>() 
       where e.IsActive 
       select e) 
      .Skip(skip) 
      .Take(pageSize) 
      .ToList(); 
    } 

NHibernate.QueryException: ne pouvait pas résoudre la propriété: YearOfEvent de: .... événement

FWIW, j'ai floutées la Nom du projet. ;)

Une idée de comment obtenir cette requête de travail?

Merci! -Steve

EDIT: Voici mon mapping class:

public class EventMap : ClassMap<Event> 
{ 
    public EventMap() 
    { 
     Table("tbl_event"); 
     Id(x => x.Id, "eventId"); 
     Map(x => x.DateOfEvent, "dateOfEvent"); 
     Map(x => x.Description, "description"); 
     Map(x => x.Title, "title"); 
     Map(x => x.Location, "location"); 
     Map(x => x.State, "state"); 
     Map(x => x.City, "city"); 
     Map(x => x.Zip, "zip"); 
     Map(x => x.HasImage, "hasImage"); 
     Map(x => x.IsActive, "isActive"); 
    } 
} 

... et ma config:

public Configuration GetConfiguration() 
    { 
     Configuration configuration; 
     var assembly = Assembly.Load(".....Data"); 
     var fluentConfig = Fluently.Configure() 
          .Database(MySQLConfiguration.Standard.ConnectionString(
              c => c.FromConnectionStringWithKey("......") 
             )) 
          .Mappings(m => m.FluentMappings.AddFromAssembly(assembly)); 
     configuration = fluentConfig.BuildConfiguration(); 
     configuration.Properties.Add("hbm2ddl.keywords", "none"); 
     return configuration; 
    } 

Je viens aussi essayé l'API Critères:

return _session.CreateCriteria(typeof (Event)) 
      .Add(Expression.Eq("IsActive", true)) 
      .Add(Expression.Eq("YearOfEvent", year)) 
      .List<Event>(); 

Pas de travail non plus.

+0

Postez vos mappings –

+0

Étrange. Cela me semble bien, je me demande si c'est peut-être le fournisseur LINQ qui essaie de faire quelque chose de fantaisie avec les propriétés. Avez-vous essayé d'exécuter la même requête sans LINQ? – Phill

+0

Phill, vient d'essayer (posté la requête) en utilisant l'API Criteria. Même exception – StephenPAdams

Répondre

4

Voici comment vous pouvez résoudre cela en utilisant les formules. Dans votre classe d'événement, convertissez ces 2 propriétés en propriétés standard:

public class Event 
{ 
    public Event() { } 
    ... 
    public virtual DateTime DateOfEvent { get; set; } 
    public virtual Int32 YearOfEvent{ get; set; } 
    public virtual Int32 MonthOfEvent { get; set; } 
    ... 
    public virtual Boolean IsActive { get; set; } 
} 

Ensuite, dans le mappage, ajoutez des formules pour remplir leurs valeurs.Je ne suis pas très positif sur la syntaxe MySQL pour récupérer le mois de l'année & mais vous avez eu une idée (je this référence):

public class EventMap : ClassMap<Event> 
{ 
    public EventMap() 
    { 
     Table("tbl_event"); 
     Id(x => x.Id, "eventId"); 
     Map(x => x.DateOfEvent, "dateOfEvent"); 
     Map(x => x.YearOfEvent).Formula("SELECT YEAR(dateOfEvent)"); 
     Map(x => x.MonthOfEvent).Formula("SELECT MONTH(dateOfEvent)");    
     ... 
     Map(x => x.IsActive, "isActive"); 
    } 
} 

Maintenant, vous pouvez les interroger comme tous les autres champs à l'aide soit LINQ ou ICriteria:

return _session.CreateCriteria(typeof (Event)) 
      .Add(Expression.Eq("IsActive", true)) 
      .Add(Expression.Eq("YearOfEvent", year)) 
      .List<Event>(); 
+0

Merci, Denis! – StephenPAdams

1

Êtes-vous automatiquement mappé cela? Parce que je suppose qu'il est tenté de mapper YearOfEvent et MonthOfEvent, et il essaie de tirer ces colonnes de la base de données, mais ils n'existent pas.

Si vous les mappez manuellement, cela ne posera aucun problème.

+0

Phill, je les mappe manuellement. J'ai posté ma configuration ainsi que ma cartographie pour cela. – StephenPAdams

2

Vous pouvez interroger les propriétés qui existent réellement dans la base de données ou qui sont introduites dans les mappages. Comme YearOfEvent n'existe que dans votre entité, vous ne pouvez pas l'utiliser dans vos requêtes, que ce soit dans LINQ-to-NH ou ICriteria.

0

Votre requête de critères ne fonctionne pas, car votre propriété "YearOfEvent" n'est pas répertoriée dans votre mappage. NHibernate ne connaît pas cette propriété et ne peut pas la traduire en un nom de colonne.

Essayez sur les propriétés qui l'interrogation sont effectivement mis en correspondance au lieu de propriétés calculées ou calculer la propriété directement dans votre requête ...

Cependant, votre requête LINQ semble que cela devrait fonctionner, je ne vois pas comment cette erreur peut se produire avec cette requête & mapping ...

2

La technique que j'utilise est de forcer l'exécution de NHLinq puis utiliser LINQ pour terminer le filtrage. C'est techniquement ce qui doit arriver puisque NH n'est pas conscient des propriétés non-mappées comme Event.YearOfEvent. Il ressemblerait à quelque chose comme ceci:

_session.Linq<Event>() 
.Where(e => e.IsActive) 
.ToArray() // force evaluation of expression 
.Where(e => e.YearOfEvent == DateTime.Now.Year); // evaluated by LINQ, not NHLinq 

Remarque: Vous pouvez utiliser l'une des autres méthodes que la force d'évaluation (par exemple, ToList()). Cette technique ne dépend pas de ToArray() spécifiquement.

Questions connexes