2017-01-31 14 views
0

У меня есть модель клиента, который имеет множество свойств, такие как имя, фамилия, адрес, ...Создание ICriterion перебирая свойства через PropertyInfo для NHibernate сессии

Через ClientEditViewModel я могу изменить значение свойств в TextBoxes.

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); } 
    } 

    ... 
} 

Когда пользователь нажимает кнопку поиска, я хочу выполнить итерацию по всем свойствам. Если свойство не пустое или пустое, я хочу добавить их в запрос с ограничением «LIKE». Вместо того чтобы проверять каждое свойство вручную, я хотел повторить все свойства через 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; 
} 

К сожалению, когда я использую это соединение в следующем коде, я получаю сообщение об ошибке. Как я могу перебирать все свои свойства без проверки каждого отдельного свойства вручную?

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: Ауф умирают переменной "с" ВОМ Typ "Rechnungsprogramm.Model.Client" вирда Bereich вом "" verwiesen, Sie ист jedoch Nicht definiert.

System.InvalidOperationException: переменная 'с' типа 'Rechnungsprogramm.Model.Client' ссылается из сферы '', но он не определен

Собственное решение:

Не самое красивое решение, но оно работает.

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; 
} 

ответ

0

Вы не можете поместить что-нибудь, что вам нравится, в лямбда, которое должно быть переведено на SQL с помощью ORM.
Ваш лямбда должен быть переведен на SQL, который не имеет аналогов на такие вещи, как GetType, GetProperty, GetValue.

Вы можете вместо использования лямбда попытаться построить Expression динамически, немного как это question ответов.

+0

Ah ok thank you @ Frédéric :) Я попробую его с помощью динамического выражения 'Expression' –

+0

. Берегитесь, вы не можете напрямую использовать динамику Microsoft, так как это для LINQ, для которого [tag: queryover] нет. Вам нужно будет переключиться на [tag: linq-to-nhibernate], чтобы использовать его. Но вы можете изучить его реализацию, чтобы найти, как создавать свои собственные выражения динамически. (Чтение ссылок этого [ответа] (http://stackoverflow.com/a/1292639/1178314) может быть более простым). –