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?

1 Answer 1

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);
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.