2009-12-18 2 views
1

Я хочу создать общее окно поиска, используя linq to sql.Динамический построенный запрос Linq to SQL

Это то, что я пытался сделать:

class SearchWindow<T> : Form : Where T: class 
{ 
    public SearchWindow(Func<T, string> codeSelector, 
         Func<T, string> nameSelector) 
    { 
     var db = new DataContext(); 
     var table = db.GetTable<T>(); 
     var query = from item in table where 
         codeSelector(item).Contains(someText) && 
         nameSelector(item).Contains(someOtherText) 
        select item; 
    } 
} 

И я пытался использовать его как:

var searchWindow = new SearchWindow<SomeTable>(x => x.CodeColumn, 
               y => y.NameColumn).Show(); 

Bud saddly, что не работает, я прочитал о деревья выражений так я пытался сделать это с ними, и я получил:

public SearchWindow(codeColumn, nameColumn) 
{ 
    Table<T> table = db.GetTable<T>(); 
    var instanceParameter = Expression.Parameter(typeof(T), "instance"); 
    var methodInfo = typeof(string).GetMethod("Contains", 
               new Type[] { typeof(string) }); 
    var codigoExpression = Expression.Call(Expression.Property(instanceParameter, 
               codeColumn), 
              methodInfo, 
              Expression.Constant("someText", 
               typeof(string))); 
    var nombreExpression = Expression.Call(Expression.Property(instanceParameter, 
               nameColumn), 
              methodInfo, 
              Expression.Constant("someOtherText", 
               typeof(string))); 
    var predicate = Expression.Lambda<Func<T, bool>>(
     Expression.And(codigoExpression, nombreExpression), instanceParameter); 
    var query = table.Where(predicate); 
} 

и использовать его мне нужно сделать:

new SearchWindow<SomeTable>("codeColumn", "nameColumn"); 

Но я не нравлюсь подход необходимо ввести имена столбцов в виде строки, есть ли способ сделать это в моде, подобной мой первый подход (для того, чтобы иметь IntelliSense и сильную типизацию) ?

Благодарим за помощь.

+0

Я думаю, что недостающие части являются «Expression.Invoke» и «Expression.AndAlso»; Я попытался показать в примере. –

ответ

2

непроверенная, но что-то вроде:

static IQueryable<T> Search<T>(
     IQueryable<T> source, 
     Expression<Func<T, string>> codeSelector, 
     Expression<Func<T, string>> nameSelector, 
     string code, string name) 
    { 

     var row = Expression.Parameter(typeof(T), "row"); 
     var body = Expression.AndAlso(
      Expression.Call(
       Expression.Invoke(codeSelector, row), 
       "Contains", null, 
       Expression.Constant(code, typeof(string))), 
      Expression.Call(
       Expression.Invoke(nameSelector, row), 
       "Contains", null, 
       Expression.Constant(name, typeof(string)))); 
     var lambda = Expression.Lambda<Func<T, bool>>(body, row); 
     return source.Where(lambda); 
    } 

Проходите в таблице (GetTable<T>) в качестве source и лямбды, чтобы указать столбцы (x => x.CodeColumn/y => y.NameColumn и т.д.).


Обновление; протестирована на LINQ-to-Objects, я надеюсь, что это будет работать на LINQ к SQL, а также:

 var data = new[] { 
      new { Code = "abc", Name = "def"}, 
      new { Code = "bcd", Name = "efg"}, 
      new { Code = "ghi", Name = "jkl"} 
     }.AsQueryable(); 

     var filtered = Search(data, x => x.Code, x => x.Name, "b", "f"); 
     var arr = filtered.ToArray(); 
+0

Это работает !, большое спасибо – albertein

Смежные вопросы