2
var row = parser.ReadFields();
Expression<Func<DataRow, bool>> expression = null;
foreach (var pairToCheck in mappingDictionary)
{
    Expression<Func<DataRow, bool>> newCondition = r => r[pairToCheck.Value].ToString() == row[pairToCheck.Key];
    if (expression == null)
        expression = newCondition;
    else
        expression = Expression.And(expression, newCondition.Body); // Compile error, I can't do this apparently
}

var recordFound = dt.AsEnumerable().Where(expression.Compile()).Count() > 0;

See code above, I'm trying to find a record in a DataTable (var dt), but the amount of conditions that this record has to satisfy, is variable. I tried to add conditions with Expression.And, but it turns the expression into type BinaryExpression and I can no longer turn it back to the original Expression<Func<DataRow, bool>>. What am I missing here? Is my approach at least correct?

phuzi
  • 12,078
  • 3
  • 26
  • 50

1 Answers1

1

You need to have a little bit more complicated handling. Something like this:

Expression expression = null;
var parameter = Expression.Parameter(typeof(DataRow)); // create a parameter for your future lambda
foreach (var pairToCheck in mappingDictionary)
{ 
   Expression<Func<DataRow, bool>> newCondition = r => r[pairToCheck.Value].ToString() == row[pairToCheck.Key];
   // build new body replacing parameter to correct one
   var newBody = newCondition.Body.ReplaceParameter(newCondition.Parameters.First(), parameter); 

   if (expression == null) 
       expression = newBody; 
   else 
       expression = Expression.AndAlso(expression, newBody); // use AndAlso, And is a bitwise AND operation
}

var result = Expression.Lambda<Func<DataRow, bool>>(expression, parameter); // construct lambda
var recordFound = dt.AsEnumerable().Where(result.Compile()).Count() > 0;

And the ReplaceParameter method comes form:

public static class ExpressionExt
{
    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterReplacingVisitor { Source = source, Target = target }.Visit(expression);
    }

    class ParameterReplacingVisitor : ExpressionVisitor
    {
        public ParameterExpression Source;
        public Expression Target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == Source ? Target : base.VisitParameter(node);
        }
    }
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132