2010-08-11 2 views
2

ASP.NET MVC에서 동적 검색 화면을 만들었습니다. 엔티티에서 리플렉션을 통해 필드 이름을 검색하여 사용자가보기의 모든 필드를 표시하는 대신 검색하려는 필드를 선택할 수있게 할 수있었습니다.다이나믹 필드 이름을 사용하여 LINQ로 엔터티 쿼리

검색 결과가 컨트롤러에 다시 게시되면 FieldName과 Value가 포함 된 FormCollection이 나타납니다. 얼마나 많은 필드가 검색되고 있는지 모르며 FormCollection에는 사용자가 선택한 필드 만 포함됩니다.

은 내가 예를 들어 데이터베이스를 쿼리 할 때 지금 필드 이름을 내 LINQ 문에 그것을 적용 할 수 있도록하려면 : 내가 가지고 그것을 "fieldName에로 키 문자열을 사용"

public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary) 
{ 
    List<People> searchResults = new List<People>(); 

    foreach (string key in fieldValueDictionary.Keys) 
    { 
     searchResults.Add(entities.People.Where(p => p.<use the key string as the fieldName> == fieldValueDictionary[key])); 
    } 

    return searchResults; 
} 

p => p.FirstName == fieldValueDictionary [key]와 같습니다. 여기서 key = "FirstName"입니다. 나는 시도하고 람다 표현 나무를 사용하지 못했습니다, 그리고 동적 LINQ와 약간의 성공을했습니다.

public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary) 
{ 
    IQueryable<People> results = entities.People; 

    foreach (string key in fieldValueDictionary.Keys) 
    { 
     switch (k) 
     { 
      case "FirstName": results = results.Where(entities.People.Where(p => p.FirstName == k); 
      case "LastName": results = results.Where(entities.People.Where(p => p.LastName == k); 
      // Repeat for all 26 fields in table 
     } 
    } 

    return results.ToList<People>(); 
} 

UPDATE : 다른 유일한 대안은 같은 것을 할 것입니다 나는 다음과 같은 게시물을 통해 람다 식 나무에 대한 연구를 수행했습니다

dynamically create lambdas expressions + linq + OrderByDescending

Parameter problem with Expression.Lambda()

LINQ: Passing lambda expression as parameter to be executed and returned by method

나는 지금까지 다음을 출력하는 람다를 얻는 것 : "p => p.FirstName", 그러나 나는 이것을 어디에서 작동시키는 지 알 수 없다. 어떤 제안? 내 코드는 다음과 같습니다 :

MemberInfo member = typeof(People).GetProperty("FirstName"); 
ParameterExpression cParam = Expression.Parameter(typeof(People), "p");  
Expression body = Expression.MakeMemberAccess(cParam, member);   

var lambda = Expression.Lambda(body, cParam); 
+1

당신은 정말 당신이 표현의 나무를 사랑하는 법을 배워야 필요 해요 생각, 동적 거동 이런 종류의합니다. –

답변

6

은 많은 시행 착오 및 검색 후 실수로 같은 문제를 다루고 다른 SO 게시물을 발견 :

여기 InvalidOperationException: No method 'Where' on type 'System.Linq.Queryable' is compatible with the supplied arguments

일 내 수정 된 코드입니다 :

 IQueryable query = entities.People; 
     Type[] exprArgTypes = { query.ElementType }; 

     string propToWhere = "FirstName";    

     ParameterExpression p = Expression.Parameter(typeof(People), "p"); 
     MemberExpression member = Expression.PropertyOrField(p, propToWhere); 
     LambdaExpression lambda = Expression.Lambda<Func<People, bool>>(Expression.Equal(member, Expression.Constant("Scott")), p);        

     MethodCallExpression methodCall = Expression.Call(typeof(Queryable), "Where", exprArgTypes, query.Expression, lambda); 

     IQueryable q = query.Provider.CreateQuery(methodCall); 

일부 변경 사항을 적용하면 모든 유형에서 작동 할 수 있습니다.

덕분에 다시 답변 애니 & 존 보웬

1
public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary) 
     { 
      return !fieldValueDictionary.Any() 
        ? entities.People 
        : entities.People.Where(p => fieldValueDictionary.All(kvp => PropertyStringEquals(p, kvp.Key, kvp.Value))) 
            .ToList(); 
     } 

    private bool PropertyStringEquals(object obj, string propertyName, string comparison) 
     { 
      var val = obj.GetType().GetProperty(propertyName).GetValue(obj, null); 
      return val == null ? comparison == null : val.ToString() == comparison; ; 
     } 
+0

이 컨텍스트에서이 엔티티는 무엇입니까? – duardbr

5

당신이 PropertyInfo에서 값을 받고 시도?

entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key]) 
+1

Entity에 대한 Linq는 GetValue() 호출을 지원하지 않습니다. 이 아이디어를 적용 할 수는 있지만 DB에서 전체 사람 목록을 가져 와서 내가 필요로하는 것보다 깨끗하지만 그 사람을 통해 foreach해야합니다. –