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