2012-01-25 9 views
0

データベースからの任意のタプルを慣習的にCLRオブジェクトにマップする簡単なクラスを開発しています。LINQ式ツリー解析の問題

私の仕事では、データベースが巨大でモデルが分割されており、異なるコンテキストを交差することができないため、私はEntityFrameworkを使用できません。

私は独自のORMマッパーを開発し始めました。これは、挿入、更新、および削除コマンドを生成します。 私はselect CMDを生成するselectメソッドを開発しようとしています。

このメソッドは、データをフィルタリングするパラメータでExpression<T, bool>フィルタを受け取ります。私は本当に使いたい

ことの一つは、のようなものされています。大きな問題は、私が本当にやりたいこと」の値を交換することで、

int value = 1; 
int valu2 = 40; 

mapper.Select<MyEntity>(m => m.id> value && m.id<= value2); 

をあるようfilter.body.toString()が文字列を生成していることで、値 "と"値2 "を変数に宣言した値で表します。

誰かが私に光を与えることができますか?

本当にありがとうございます!

答えて

0

フィルタを構築するために、簡単な方法でexprツリーを解析しました。

ここで私はそれをしました。

private static String ParseFilter(Expression expr) 
    { 
     return ParseFilter(expr, new ExpressionUtilFilterClass()).data.ToString(); 
    } 

    // Recursive algorithm 
    private 
    static 
    ExpressionUtilFilterClass       // Return type 
    ParseFilter(
     Expression expr, 
     ExpressionUtilFilterClass info   // Used to pass information in recursive manner 
    ) 
    { 

     Type exprType = expr.GetType(); 

     if (exprType != typeof(BinaryExpression) && exprType != typeof(MemberExpression) && exprType != typeof(ConstantExpression)) 
      throw new InvalidOperationException("unsupported filter"); 


     if (exprType == typeof(BinaryExpression)) 
     { 
      // 
      // We have 2 expressions (left and right) 
      // 

      BinaryExpression bExpr = (BinaryExpression)expr; 
      ExpressionUtilFilterClass recursion; 

      StringBuilder subOperation = new StringBuilder(); 
      recursion = ParseFilter(bExpr.Left, info);    // Go left in depth - we don't know the type yet 

      subOperation.Append("("); 
      subOperation.Append(recursion.data); 
      subOperation.Append(" "); 

      subOperation.Append(_expressionOperator[bExpr.NodeType]); 
      subOperation.Append(" "); 

      recursion = ParseFilter(bExpr.Right, recursion);    // Pass reference that contains type information! 

      subOperation.Append(recursion.data); 
      subOperation.Append(")"); 

      // Affect data subpart and pass to upper caller 
      recursion.data = subOperation.ToString(); 

      return recursion; 
     } 

     else 
     { 
      MemberExpression mExpr; 
      ParameterExpression pExpr; 
      ConstantExpression cExpr; 

      // 
      // We need distinct if we are accessing to capturated variables (need map to sql) or constant variables 
      // 

      if ((mExpr = expr as MemberExpression) != null) 
      { 
       if ((pExpr = (mExpr.Expression as ParameterExpression)) != null) 
       { 
        info.parameterType = mExpr.Expression.Type;  // Type of parameter (must be untouched) 
        info.data = GetMappingForProperty(info.parameterType, mExpr.Member.Name);      // Must have a map to SQL (criar metodo que faz mapeamento)!!!!!!!!!!!!!!!!! 

        return info; 
       } 
       else 
       { 
        cExpr = (ConstantExpression)mExpr.Expression; 

        object obj = cExpr.Value;    // Get anonymous object 
        string objField = mExpr.Member.Name; 

        FieldInfo value = obj.GetType().GetField(objField); // Read native value 
        string nativeData = value.GetValue(obj).ToString(); 

        info.data = nativeData; 
        return info; 
       } 
      } 
      else 
      { 
       cExpr = (ConstantExpression)expr; 
       string nativeData = cExpr.Value.ToString(); 

       info.data = nativeData; 
       return info; 
      } 
     } 
    } 
1

これを達成する簡単な方法はありません。 Expression Tree Basicsのブログを参照してください

WHERE id > 1 AND id < 40

:あなたは再帰的に全体の構文木を解析し、このようになりますwhere句、それを変換する必要があります。あなたの質問に対する完全な答えではありません。しかし、それはあなたに出発点を与えるかもしれません。