我有以下代码来构建IQueryable
Expression<Func<TParentEntity, TChildEntity, bool>> joinExpr =
ctx.GetJoinExpression<TParentEntity, TChildEntity>();
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity>(ctx);
return
from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
let childEntities =
from child in ctx.GetQueryable<TChildEntity>()
where joinExpr.Invoke(parentEntity, child)
select child
where childEntities.Any(childSelectionExpression)
select parentEntity;
我一直在尝试(不成功地)构建将返回相同结果的表达式树。
我想要一个表达式Expression<Func<TParentEntity,bool> parentExpression
我可以使用如下:
from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
where parentExpression.Invoke(parentEntity)
select parentEntity
有人认为这是可能的吗?我相信,但我无法解决它......
答案 0 :(得分:0)
我知道你想要什么,因为我已经尝试过,我很遗憾地通知你,你已经到了痛苦的世界。以下是部分解决方法:
Expression<Func<TParentEntity, TChildEntity, bool>> joinExpr =
ctx.GetJoinExpression<TParentEntity, TChildEntity>();
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity>(ctx);
return
(from parentEntity in ctx.GetQueryable<TParentEntity>()
.AsExpandable()
let childEntities =
from child in ctx.GetQueryable<TChildEntity>()
where joinExpr.Invoke(parentEntity, child)
select child
select parentEntity).Where(childSelectionExpression);
你必须转换所有使用表达式变量的查询调用,就像我做的那样。并非总是可行,但我认为在你的情况下它是。
答案 1 :(得分:0)
Eureaka: - )
这篇文章末尾的方法返回一个类型为Expression<Func<TParentEntity,bool>>
的表达式,让我们称之为parentExpression。
当像这样使用时:
var data = (from parentEntity in parentEntities.AsExpandable()
where parentExpression.Invoke(parentEntity) select parentEntiy).ToList()
实际发生的事情是这样的:
var data = (from parentEntity in parentEntities.AsExpandable()
let childeren = childEntities.Where(c => c.parentId = parentEntity.Id)
where childeren.Any([childSelectionLambda])
select parent).ToList()
能够在一个类型为λ的Lambda中表达子标准
Expression<Func<TParentEntity, bool>>
使用PredicateBuilder.And()很容易将多个子标准(表示为父标准)或其他(正常)父标准组合在一起。
EF和linq to SQL(和sql ce)的测试是绿色的: - )
override public Expression<Func<TParentEntity, bool>>
GetParentExpression<TParentEntity>( IDynamicQueryAdapter ctx )
{
// Define parameters needed in expresion tree
ParameterExpression parentParameter =
Expression.Parameter (typeof (TParentEntity), "parent");
ParameterExpression childParameter =
Expression.Parameter (typeof (TChildEntity), "child");
// Define the IQueryable<TChildEntity> as
// a constant for use in the expression tree.
IQueryable<TChildEntity> childDatasource =
ctx.GetQueryable<TChildEntity>().AsExpandable();
ConstantExpression childDatasourceConstant =
Expression.Constant (childDatasource);
// Get MethodInfo instance, needed for the MethodCallExpression
MethodInfo anyMethodInfoChildEntity =
QueryHelper.GetQueryableAnyMethod<TChildEntity> ();
// Get the lambda expression
// required to select only those child entities
// which meet the user defined criteria
Expression<Func<TChildEntity, bool>> childSelectionExpression =
GetExpression<TChildEntity> (ctx);
// Use the ExpressionParameter childParamter for the
// ChildSelectionExpression and strip Expression.Invoke using Expand()
Expression<Func<TChildEntity, bool>> lambda5 =
Expression.Lambda<Func<TChildEntity, bool>> (
Expression.Invoke (childSelectionExpression, childParameter),
childParameter).Expand ();
#region Express the parent child relation
PropertyInfo parentKeyPropertyInfo = null;
PropertyInfo childKeyPropertyInfo = null;
ctx.GetParentChildAssociationProperties (
typeof (TParentEntity), typeof (TChildEntity),
out parentKeyPropertyInfo, out childKeyPropertyInfo);
Expression parentPropertyExpression =
Expression.Property (parentParameter, parentKeyPropertyInfo.Name);
Expression childPropertyExpression =
Expression.Property (childParameter, childKeyPropertyInfo.Name);
if( childKeyPropertyInfo.PropertyType != parentKeyPropertyInfo.PropertyType )
{
// TODO: what if the property types are incomparable >> exception.
// some more code is needed!!
Type nullableParentType =
typeof (Nullable<>)
.MakeGenericType (parentKeyPropertyInfo.PropertyType);
if( childKeyPropertyInfo.PropertyType == nullableParentType )
{
childPropertyExpression =
Expression.Convert (childPropertyExpression,
parentKeyPropertyInfo.PropertyType);
}
else if( childKeyPropertyInfo.PropertyType.IsValueType )
{
Type nullableChildType =
typeof (Nullable<>).MakeGenericType (childKeyPropertyInfo.PropertyType);
if( parentKeyPropertyInfo.PropertyType == nullableChildType )
{
parentPropertyExpression =
Expression.Convert (parentPropertyExpression,
childKeyPropertyInfo.PropertyType);
}
}
}
#endregion
var lambda4 = Expression.Lambda<Func<TChildEntity, bool>> (
Expression.Equal (
parentPropertyExpression,
childPropertyExpression), childParameter );
var predicate = lambda4.And(lambda5).Expand();
Expression<Func<TParentEntity, bool>> parentSelectionExpression =
Expression.Lambda<Func<TParentEntity,bool>>(
Expression.Call (
null,
anyMethodInfoChildEntity,
new Expression[] { childDatasourceConstant, predicate }),
new[]{parentParameter});
return parentSelectionExpression;
}
注意:PredicateBuilder,扩展名AsExpandable(),扩展名Expand()...是LinqKit的一部分 有关这些访问的更多信息:Linqkit into