locked
Expression Trees and datarow RRS feed

  • Question

  • i need to build an expression tree for this query:

      IQueryable<DataRow> tempResults....
      var test = from datarow in tempResults
                      where datarow.Field<String>("ColumnName") == "Hello"
                      select datarow;
    
    

    but how do i build the "datarow.Field<String>("ColumnName")" ?

    i started something but i don't know if it's right and how to finish:

     ParameterExpression oneDataRow = Expression.Parameter(typeof(DataRow), "dataRow");
    
                Expression columnName = Expression.Property(oneDataRow, typeof(DataRow).Get......);
    
    


    is it really an expression property ? how do i create the Field<String> ?

     

    Wednesday, August 19, 2009 1:11 PM

Answers

  • Hi rodniko,

    The MethodInfo for Field<T>(DataRow, String) can be retrieved by:

    ==============================================================================================
    MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });
    ==============================================================================================

    Then the expression tree of datarow.Field<String>(“ColumnName”) can be built as:

    ==============================================================================================
                // Retrieve the MethodInfo of the generic Field<String>(this DataRow, String) method

                MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });

                mi = mi.MakeGenericMethod(typeof(string));

     

                List<Expression> list = new List<Expression>();

     

                // ParameterExpression

                //      Name: String: “datarow”

                //      NodeType: ExpressionType: “Parameter”

                //      Type: Type: “DataRow”

                ParameterExpression datarow = Expression.Parameter(typeof(DataRow), "datarow");

     

                // ConstantExpression

                //      Value: Object: “ColumnName”

                //      NodeType: ExpressionType: “Constant”

                //      Type: Type: “String”

                ConstantExpression constant = Expression.Constant("ColumnName", typeof(string));

     

                // Add the Expression into List

                list.Add(datarow);

                list.Add(constant);

     

                // Copy the List<Expression> elements into ReadOnlyCollection<Expression>

                ReadOnlyCollection<Expression> collection = new ReadOnlyCollection<Expression>(list);

     

                // MethodCallExpression

                //      Method: MethodInfo:  “Field<String>”

                //      Object: Expression: null

                //      Arguments: ReadOnlyCollection<Expression>

                //          ...

                //      NodeType: ExpressionType: “Call”

                //      Type: Type: “String”

                MethodCallExpression methodCall = Expression.Call(null, mi, collection);
    ==============================================================================================

    Based on these codes and the help of Expression Tree Visualizer, you can build your own Expression Trees.


    For additional references about Expression Trees, please see
    http://msdn.microsoft.com/en-us/library/bb397951.aspx
    http://msdn.microsoft.com/en-us/library/bb546136.aspx
    http://msdn.microsoft.com/en-us/library/bb882521.aspx
    http://www.devsource.com/c/a/Languages/Understanding-LINQ-Expression-Trees/1/


    If you have any questions, please feel free to let me know.


    Have a nice day!


    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, August 25, 2009 2:20 PM

All replies

  • You don't have to implement anything. Just import System.Data and add a reference to System.Data.DataSetExtensions

    (That "Field<string>" is in DataRowExtensions class there - look up in Reflector if you're interested about implementation details)




    codevanced.net
    • Edited by codevanced Wednesday, August 19, 2009 2:16 PM
    Wednesday, August 19, 2009 2:11 PM
  • Hi rodniko,

     

    I think the datarow.Field<string>(“ColumnName”) is a MethodCallExpression.  Here is what I found in Expression Tree Visualizer. 

     

    Datarow.Field(“ColumnName”):

    ===============================================================
    MethodCallExpression

    Method: MethodInfo:  “Field<String>”

    Object: Expression: null

    Arguments: ReadOnlyCollection<Expression>

                ParameterExpression

                            Name: String: “datarow”

                            NodeType: ExpressionType: “Parameter”

                            Type: Type: “DataRow”

                ConstantExpression

                            Value: Object: “ColumnName”

                            NodeType: ExpressionType: “Constant”

                            Type: Type: “String”

    NodeType: ExpressionType: “Call”

    Type: Type: “String”


    ===============================================================

     

    The Expression Tree Visualizer can be found in C# Samples for Visual Studio 2008.  About how to use Expression Tree Visualizer to debug the Express Tress, please see
    http://blogs.msdn.com/charlie/archive/2008/02/13/linq-farm-seed-using-the-expression-tree-visualizer.aspx


    Please use the Expression Tree Visualizer to check the test.Expression property. 


     

    If you have any questions, please feel free to let me know.

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by rodniko Sunday, August 23, 2009 10:19 AM
    • Unmarked as answer by rodniko Sunday, August 23, 2009 10:20 AM
    Thursday, August 20, 2009 5:45 AM
  • The visualizer helps alot , thanks!!

    but i'm trying to prepare the expression tree for this method Field<String>
    and i need the Methodinfo of this method.

    i tried everything, but in the methodinfo i get null.
    it must be because Field<String> is an extention method of DataRow and therefore doesn't exist in DaraRow type.

    it's wierd cause it exists in the 'datarow' thats inside the linq query :
    datarow.field<String>("ColumnName")
    but not inside DataRow type.

    i tried :

    MethodInfo info = typeof(DataRow).GetMethod("Field<String>", BindingFlags.public|BindingFlags.Static);
    MethodInfo info = typeof(myQueryableData.ElementType).GetMethod("Field<String>", BindingFlags.public|BindingFlags.Static);

    but i get null
    Sunday, August 23, 2009 10:31 AM
  • Still strugling with this....

    String name = typeof(DataRowExtentions).GetMethods()[0].Name;
    MethodInfo FieldStringMethodInfo = typeof(DataRowExtentions).GetMethod(name);
    
    Error : ambigous match found
    
    
    ParameterExpression datarow = Expression.Parameter(typeof(DataRowExtentions),"dataRow");
    Expression left = Expression.Call(datarow,typeof(DataRowExpression).GetMethod("Field<String>"));
    
    Doesn't work too.
    how hard can creating the expression : datarow.field<String>("ColumnName") be....

    the whole query that i want to create is :

    var result = from datarow in tempResutlts
    where datarow.Field<String>(ColumnName) == "Column"
    select datarow;

    please help...
    • Marked as answer by rodniko Tuesday, September 1, 2009 8:57 AM
    • Unmarked as answer by rodniko Tuesday, September 1, 2009 8:57 AM
    Sunday, August 23, 2009 12:21 PM
  • Hi rodniko,

    The MethodInfo for Field<T>(DataRow, String) can be retrieved by:

    ==============================================================================================
    MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });
    ==============================================================================================

    Then the expression tree of datarow.Field<String>(“ColumnName”) can be built as:

    ==============================================================================================
                // Retrieve the MethodInfo of the generic Field<String>(this DataRow, String) method

                MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });

                mi = mi.MakeGenericMethod(typeof(string));

     

                List<Expression> list = new List<Expression>();

     

                // ParameterExpression

                //      Name: String: “datarow”

                //      NodeType: ExpressionType: “Parameter”

                //      Type: Type: “DataRow”

                ParameterExpression datarow = Expression.Parameter(typeof(DataRow), "datarow");

     

                // ConstantExpression

                //      Value: Object: “ColumnName”

                //      NodeType: ExpressionType: “Constant”

                //      Type: Type: “String”

                ConstantExpression constant = Expression.Constant("ColumnName", typeof(string));

     

                // Add the Expression into List

                list.Add(datarow);

                list.Add(constant);

     

                // Copy the List<Expression> elements into ReadOnlyCollection<Expression>

                ReadOnlyCollection<Expression> collection = new ReadOnlyCollection<Expression>(list);

     

                // MethodCallExpression

                //      Method: MethodInfo:  “Field<String>”

                //      Object: Expression: null

                //      Arguments: ReadOnlyCollection<Expression>

                //          ...

                //      NodeType: ExpressionType: “Call”

                //      Type: Type: “String”

                MethodCallExpression methodCall = Expression.Call(null, mi, collection);
    ==============================================================================================

    Based on these codes and the help of Expression Tree Visualizer, you can build your own Expression Trees.


    For additional references about Expression Trees, please see
    http://msdn.microsoft.com/en-us/library/bb397951.aspx
    http://msdn.microsoft.com/en-us/library/bb546136.aspx
    http://msdn.microsoft.com/en-us/library/bb882521.aspx
    http://www.devsource.com/c/a/Languages/Understanding-LINQ-Expression-Trees/1/


    If you have any questions, please feel free to let me know.


    Have a nice day!


    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, August 25, 2009 2:20 PM
  • Hi rodniko,

     

    I am writing to check the status of the issue on your side.  Would you mind letting me know the result of the suggestions? 

     

    If you need further assistance, please feel free to let me know.   I will be more than happy to be of assistance.

     

    Have a nice weekend!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, August 28, 2009 10:23 AM
  • I used your code as a guide for something I'm working on.  I'm getting stuck on the ParameterExpression below.

                    Expression leftExp = null;
    
                    MethodInfo mi = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), filter.MemberType });
                    mi = mi.MakeGenericMethod(filter.MemberType);
                    List<Expression> list = new List<Expression>();
                    ParameterExpression datarow = Expression.Parameter(typeof(DataRow), "datarow");
                    ConstantExpression constant = Expression.Constant(filter.PropertyName, filter.MemberType);
                    list.Add(datarow);
                    list.Add(constant);
                    ReadOnlyCollection<Expression> collection = new ReadOnlyCollection<Expression>(list);
    
                    leftExp = Expression.Call(null, mi, collection)
                    expression = Expression.Call(leftExp, "StartsWith", null, convertedRightExp, Expression.Constant(StringComparison.InvariantCultureIgnoreCase));

    The code above is part of one method and the "expression" variable becomes "finalExp" and data is of type System.Data.EnumerableRowCollection.

                    filteredSet = data.Where(finalExp.Compile());

    The value of finalExp prior to the error looks correct for what I'm doing:

    finalExp    {Param_0 => datarow.Field("Name").StartsWith("J", InvariantCultureIgnoreCase)}    System.Linq.Expressions.Expression<System.Func<System.Data.DataRow,bool>

    However, this last statement errors out with "variable 'datarow' of type 'System.Data.DataRow' referenced from scope '', but it is not defined".  The name "datarow' that is given in the ParameterExpression - what is this supposed to map to?

    Thanks in advance!


    Saturday, October 11, 2014 12:40 AM