2017-01-31 2 views
0

J'ai un modèle client qui possède de nombreuses propriétés comme le prénom, nom, adresse, ...Créer ICriterion par itérer propriétés via PropertyInfo pour NHibernate séance

Via le ClientEditViewModel je peux changer les valeurs de propriété dans les TextBox.

public class ClientEditViewModel : EditableViewModelBase 
{ 
    public int ClientID 
    { 
     get { return this.currentClient.ClientID; } 
     set { this.SetProperty(newValue => this.currentClient.ClientID = newValue, value); } 
    } 

    public string Title 
    { 
     get { return this.currentClient.Title; } 
     set { this.SetProperty(newValue => this.currentClient.Title = newValue, value); } 
    } 

    public string FirstName 
    { 
     get { return this.currentClient.FirstName; } 
     set { this.SetProperty(newValue => this.currentClient.FirstName = newValue, value); } 
    } 

    public string LastName 
    { 
     get { return this.currentClient.LastName; } 
     set { this.SetProperty(newValue => this.currentClient.LastName = newValue, value); } 
    } 

    ... 
} 

Lorsque l'utilisateur appuie sur le bouton de recherche, je souhaite parcourir toutes les propriétés. Si la propriété n'est pas vide ou nulle, je veux les ajouter à la requête avec la restriction 'LIKE'. Au lieu de vérifier chaque propriété manuellement, je voulais parcourir toutes les propriétés via Reflection.

public ICriterion GetSearchClientCriteria() 
{ 
    var conjunction = Restrictions.Conjunction(); 

    if (this.ClientID != 0) 
    { 
     conjunction.Add(Restrictions.Where<Client>(x => x.ClientID == this.ClientID)); 
     return conjunction; 
    } 

    foreach (PropertyInfo propertyInfo in this.PropertyInfosWithPublicGetterAndSetter) 
    { 
     if (propertyInfo.PropertyType == typeof(string)) 
     { 
      string currentPropertyValue = propertyInfo.GetValue(this) as string; 

      if (!string.IsNullOrEmpty(currentPropertyValue)) 
      { 
       /* This statement can be executed */ 
       // conjunction.Add(Restrictions.Where<Client>(c => c.FirstName.IsLike(this.FirstName, MatchMode.Anywhere))); 
       conjunction.Add(Restrictions.Where<Client>(c => c.GetType().GetProperty(propertyInfo.Name).GetValue(c, null).ToString() 
       .IsLike(this.GetType().GetProperty(propertyInfo.Name).GetValue(this).ToString()))); 

       return conjunction; 
      } 
     } 
    } 

    return conjunction; 
} 

Unfotunately, quand j'utilise cette conjonction dans le code suivant, je reçois une erreur. Comment puis-je parcourir toutes mes propriétés sans vérifier chaque propriété manuellement?

public class NHibernateRepository : IRepository 
{ 
    public ICollection<T> GetByCriteria<T>(ICriterion criterion) where T : class 
    { 
     using (var session = this.sessionManager.OpenSession()) 
     { 
      return session.QueryOver<T>().Where(criterion).List(); 
     } 
    } 
} 

System.InvalidOperationException: Auf die Variable "c" vom Typ "Rechnungsprogramm.Model.Client" wird vom Bereich "" verwiesen, ist sie jedoch nicht definiert.

System.InvalidOperationException: variable 'c' de type 'Rechnungsprogramm.Model.Client' référencé de champ '', mais il ne se définit pas

solution propre:

Pas la plus belle solution, mais cela fonctionne.

private ICriterion GetClientSearchCriterion() 
{ 
    Conjunction conjunction = Restrictions.Conjunction(); 

    if (this.CurrentClientDetailViewModel.ClientId != 0) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.ClientId == this.CurrentClientDetailViewModel.ClientId)); 
     return conjunction; 
    } 

    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.Title)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.Title.IsLike(this.CurrentClientDetailViewModel.Title, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.FirstName)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.FirstName.IsLike(this.CurrentClientDetailViewModel.FirstName, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.LastName)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.LastName.IsLike(this.CurrentClientDetailViewModel.LastName, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.Street)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.Street.IsLike(this.CurrentClientDetailViewModel.Street, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.HouseNumber)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.HouseNumber.IsLike(this.CurrentClientDetailViewModel.HouseNumber, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.PostalCode)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.PostalCode.IsLike(this.CurrentClientDetailViewModel.PostalCode, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.City)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.City.IsLike(this.CurrentClientDetailViewModel.City, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.DateOfBirth)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.DateOfBirth.IsLike(this.CurrentClientDetailViewModel.DateOfBirth, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.PhoneNumber1)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.PhoneNumber1.IsLike(this.CurrentClientDetailViewModel.PhoneNumber1, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.PhoneNumber2)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.PhoneNumber2.IsLike(this.CurrentClientDetailViewModel.PhoneNumber2, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.MobileNumber)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.MobileNumber.IsLike(this.CurrentClientDetailViewModel.MobileNumber, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.Telefax)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.Telefax.IsLike(this.CurrentClientDetailViewModel.Telefax, MatchMode.Anywhere))); 
    } 
    if (!string.IsNullOrEmpty(this.CurrentClientDetailViewModel.Email)) 
    { 
     conjunction.Add(Restrictions.Where<Client>(c => c.Email.IsLike(this.CurrentClientDetailViewModel.Email, MatchMode.Anywhere))); 
    } 

    return conjunction; 
} 

Répondre

0

Vous ne pouvez pas mettre quelque chose que vous aimez dans lambda devant être traduit en SQL par un ORM.
Votre lambda doit pouvoir être traduit en SQL, ce qui n'a pas d'équivalent à des choses telles que GetType, GetProperty, GetValue.

Vous pouvez, au lieu d'utiliser lambda, essayer de construire Expression dynamiquement, un peu comme ce question réponses.

+0

Ah ok merci @ Frédéric :) Je vais essayer avec la 'Expression' dynamique –

+0

Attention, vous ne pouvez pas utiliser Microsoft Dynamics directement, puisque c'est pour LINQ, ce qui n'est pas le cas de [tag: queryover]. Vous devriez passer à [tag: linq-to-nhibernate] pour l'utiliser. Mais vous pouvez étudier son implémentation pour trouver comment construire vos propres expressions dynamiquement. (Lire les liens de cette [réponse] (http://stackoverflow.com/a/1292639/1178314) pourrait être plus simple.) –