1

我在创建表达式以添加到可查询作为过滤条件时遇到了一些麻烦。我想复制以下内容:

从一个简单的可查询开始:

IQueryable<Customer> query = from customer in context.Customer
    select customer;

我想动态添加一个涉及在 DataContext 上调用方法的过滤条件:

IQueryable<Customer> query = from customer in context.Customer
    where customer.Name == context.ConvertValueForSearch(searchString)
    select customer;

以便“ConvertValueForSearch”在评估时调用适当的数据库函数。

以上产生以下SQL:

exec sp_executesql N'SELECT [t0].[CustName]
   FROM [dbo].[Customer] AS [t0]
   WHERE [t0].[CustName] = [dbo].[fnConvertSearchStringValue](@p0)',N'@p0 varchar(8000)',@p0='Foo'

我们有许多 DataContext 派生类型,因此 ConvertValueForSearch 是通过每个 DataContext 类型实现的接口 (ISearchValueConverter) 定义的。

我不确定如何正确创建表达式以在 DataContext 上调用 ConvertValueForSearch(string searchValue),然后创建由 Customer.Name 的属性访问器和对 ConvertValueForSearch 的方法调用组成的最终 Expression.Equal 以便过滤器可以通过 CreateQuery 应用于可查询对象。

如果我从以下内容开始:

... code executed in the repository instance
<Func<Manager<TEntity, TRootDal, TUniqueIdentifierType>, string, string>> convertSearchStringValueLambda =
    (manager, searchValueToConvert) => manager.DataContextForConversionForSpecificContext.ConvertValueForSearch(searchValueToConvert);
var invokedCall = Expression.Invoke(convertSearchStringValueLambda, Expression.Constant(this), Expression.Constant(searchValue));

...code executed in the filter item instance to apply the filter to the queryable
// the accessor for Customer.Name    
LambdaExpression propertyAccessor = Entity<TDalEntity>.GetPropertyAccessorExpression<string>(this.FilterField);
BinaryExpression filterExpression = Expression.Equal(propertyAccessor.Body, filterValue);

Expression filter = Expression.Lambda(filterExpression, propertyAccessor.Parameters);

query = query.Provider.CreateQuery<TDalEntity>(
    Expression.Call(
        typeof(Queryable),
        "Where",
        new Type[] { query.ElementType },
        query.Expression,
        filter));

对 fnConvertSearchStringValue 的调用是在对 db 的单独调用中完成的,并且在使用可查询对象时将其结果传递给数据库。尽管在某些情况下这可能没问题,但我确实需要在使用上面的 Linq-to-SQL 生成的 SQL 中调用该函数。

感谢您的任何建议。

4

0 回答 0