2011-02-01 11 views
2

私は同じ結果を返す式ツリーを構築(unsuccesfully)しようとしてきたの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

'GetJoinExpression'は何をしますか? O/RMとは何ですか? – Steven

+0

http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspxを参考にしてください。 –

+0

GetJoinExpressionは、親と子の間の関係を表す式を作成します。 これは、リフレクションを使用して実装されています。AssociationAttributeを検索します。これは、式で使用するプロパティ名を提供します。 –

答えて

0

Eureaka :-)

方法は、タイプExpression<Func<TParentEntity,bool>>の表現を返し、のはparentExpression 1つを呼び出してみましょう。

このように使用:


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()

タイプのラムダに子基準を表現することができることによって


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()、extenstionは(展開が)... LinqKit 用の一部でありますこれらの訪問についての詳細情報:Linqkit into

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); 

私がしたように、式の変数を使用するすべてのクエリ呼び出しを変換する必要があります。いつも可能なわけではありませんが、私はあなたのケースではそうだと思います。この記事の最後に

+0

本当に痛みの世界です。 –

関連する問題