How to reuse where clauses in Linq To Sql queries

前端 未结 4 1349
谎友^
谎友^ 2020-12-08 22:35

I have users searching records of type Record. They type a search term in a textbox and then I search records by matching several fields with the search term.

My que

相关标签:
4条回答
  • 2020-12-08 23:08

    In addition to the Expression<Func<Record, bool>> issue that others have pointed out, I suggest looking into PredicateBuilder. It's very good for dynamically combining lambda expressions.

    0 讨论(0)
  • 2020-12-08 23:15

    Use a CompiledQuery!

    var filter = CompiledQuery.Compile(
        (DatabaseDataContext dc, Record record, string term) =>
            record.Field1.ToLower().Contains(term) ||
            record.Field2.ToLower().Contains(term) ||
            record.Field3.ToLower().Contains(term)
    );
    
    var results = from record in DataContext.Records
                  where filter(DataContext, record, term)
                  select record;
    

    For more information, see How to: Store and Reuse Queries.

    0 讨论(0)
  • 2020-12-08 23:17

    I think you need to make it an Expression<Func<Record, bool>>. Otherwise it's trying to translate the actual C# method call to SQL rather than the description of it. This is not a guarantee that this version will work; I'm not sure which string functions are translatable to SQL.

    0 讨论(0)
  • 2020-12-08 23:21

    You need to build an expression instead of a function:

    Expression<Func<Record, bool>> filter = 
      record => record.Field1.ToLower().Contains(term);  // rest omitted
    

    The lambda expression remains the same, but you need to return it into a variable of type Expression<Func<Record, bool>> -- that will make the C# compiler compile it as an expression instead of a delegate, allowing it to be passed to LINQ to SQL.

    However, you won't be able to use an expression variable with a C#-syntax where clause: you'll need to use the Where extension method:

    var results = DataContext.Records.Where(filter);
    

    Edited to add: If you want to be able to create filters on different terms, you just need a method to produce an expression from a term:

    private static Expression<Func<Record, bool>> Filter(string term)
    {
      return r => r.Field1.ToLower().Contains(term);
    }
    
    var results = DataContext.Records.Where(Filter(term));
    

    If you prefer to keep filter as a lambda as you have at the moment, you can do so, but the generics get a bit nested:

    Func<string, Expression<Func<Record, bool>>> filter =
      term => (r => r.Field1.ToLower().Contains(term));
    
    var results = DataContext.Records.Where(filter(term));
    

    Regardless, the important thing is that what goes in the Where clause must be an Expression<Func<Record, bool>> -- but as shown above you can make the expression depend on term by building a suitable expression on the fly. Which is exactly what LINQ to SQL would be doing if you spelled out the filter longhand in the Where clause.

    0 讨论(0)
提交回复
热议问题