我在创建表达式以添加到可查询作为过滤条件时遇到了一些麻烦。我想复制以下内容:
从一个简单的可查询开始:
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 中调用该函数。
感谢您的任何建议。