我一直很感兴趣地关注这里的对话:
关于构造表达式树,即使表名也是动态的。
为此,我创建了一个Extension方法addWhere,它类似于:
static public IQueryable<TResult> addWhere<TResult>(this IQueryable<TResult> query, string columnName, string value)
{
var providerType = query.Provider.GetType();
// Find the specific type parameter (the T in IQueryable<T>)
var iqueryableT = providerType.FindInterfaces((ty, obj) => ty.IsGenericType && ty.GetGenericTypeDefinition() == typeof(IQueryable<>), null).FirstOrDefault();
var tableType = iqueryableT.GetGenericArguments()[0];
var tableName = tableType.Name;
var tableParam = Expression.Parameter(tableType, tableName);
var columnExpression = Expression.Equal(
Expression.Property(tableParam, columnName),
Expression.Constant(value));
var predicate = Expression.Lambda(columnExpression, tableParam);
var function = (Func<TResult, Boolean>)predicate.Compile();
var whereRes = query.Where(function);
var newquery = whereRes.AsQueryable();
return newquery;
}
[感谢Timwi作为该代码的基础]
在功能上起作用。
我可以打电话:
query = query.addWhere("CurUnitType", "ML 15521.1");
它在功能上等效于:
query = query.Where(l => l.CurUnitType.Equals("ML 15521.1"));
也就是说,返回的行是相同的。
但是,我开始查看sql日志,并注意到以下内容:
query = query.Where(l => l.CurUnitType.Equals("ML 15521.1"));
生成的查询是:
SELECT (A bunch of columns)
FROM [dbo].[ObjCurLocView] AS [t0]
WHERE [t0].[CurUnitType] = @p0
而当我用线
query = query.addWhere("CurUnitType", "ML 15521.1");
生成的查询是:
SELECT (the same bunch of columns)
FROM [dbo].[ObjCurLocView] AS [t0]
因此,现在比较是在客户端进行的,而不是添加到sql中。
显然,这并不那么热门。
坦白地说,我主要是从Timwi的(略有不同)示例中剪切并粘贴了addWhere代码,因此其中有些超出了我的理解。我想知道是否可以对此代码进行任何调整,因此将表达式转换为SQL语句,而不是确定为客户端
感谢您抽出宝贵的时间阅读本文档,我欢迎任何可以帮助我的意见,解决方案,链接等。当然,如果我通过其他方法找到解决方案,我将在此处发布答案。
干杯。
最大的问题是您要将表达式树转换为委托。查看Queryable.Where
的签名-在Queryable.Where
-它是在表达式树中而不是在委托中表示的。所以实际上是在调用Enumerable.Where
。这就是为什么您需要随后调用AsQueryable
的原因-但这在这里没有足够的魔力。它实际上并没有把它放回“内部仅表达树”的领域,因为您仍然可以在那里获得委托。它现在被包装在一个表达式树中,但是您丢失了内部发生的事情的详细信息。
我怀疑您想要的是什么:
var predicate = Expression.Lambda<Func<TResult, Boolean>>
(columnExpression, tableParam);
return query.Where(predicate);
我很容易承认我还没有阅读其余的代码,因此可能还会发生其他事情……但这就是核心。您需要一个强类型的表达式树(因此可以调用Expression.Lambda
的通用形式),然后可以将其传递到Queryable.Where
。试一试 :)