Combine multiple Linq expressions

I am refactoring some code, trying to make it more self-documenting. In the current code, there is an OData service request that looks like this:

return context.MessageLog.Where
(
    x => 
    (
        x.Status == MessageStatus.Success 
        || x.Status == MessageStatus.Failure
    ) 
    && x.Direction == MessageDirection.Inbound 
    && x.ResponseDate == new DateTimeOffset(new DateTime(1900, 01, 01))
);

I hope to change this to use Linq expressions.
I could move all the logic into a single expression and run the code context.MessageLog.Where(MessageIsPendingResponse);. However, I would like to create expressions for different conditions: MessageIsProcessed(i.e., now with success or failure), MessageIsInboundand ResponseNotYetSent(date of answer is zero). I could combine them with a few examples, such as:

return context.MessageLog
    .Where(MessageLogExpression.MessageIsProcessed)
    .Where(MessageLogExpression.MessageIsInbound)
    .Where(MessageLogExpression.ResponseNotYetSent);

( MessageLogExpressionis the class that I use to store these predefined expressions).

Question 1

(, Linq ( SQL) , ?

2

, AND, ; OR? , , . , ?

return context.MessageLog.Where(new OrExpression(MessageIsSuccess,MessageIsFailure));

3

. - ( )?

public static Expression<Func<MessageLogRecord, bool>> MessageIsPendingResponse
{
    get
    {
        Expression<Func<MessageLogRecord, bool>> expr = x => 
            MessageIsProcessed(x) 
            && MessageIsInbound(x) 
            && ResponseNotYetSent(x);
        return expr;
    }
}

: , :

public class MessageLogExpression
{
    public static Expression<Func<MessageLogRecord, bool>> MessageIsProcessed
    {
        get
        {
            Expression<Func<MessageLogRecord, bool>> expr = x => 
            (
                x.Status == MessageStatus.Success 
                || x.Status == MessageStatus.Failure
            );
            return expr;
        }
    }
    public static Expression<Func<MessageLogRecord, bool>> MessageIsInbound
    {
        get
        {
            Expression<Func<MessageLogRecord, bool>> expr = x => 
                x.Direction == MessageDirection.Inbound;
            return expr;
        }
    }
    static readonly DateTimeOffset NullDate = new DateTimeOffset(new DateTime(1900, 01, 01));
    public static Expression<Func<MessageLogRecord, bool>> ResponseNotYetSent
    {
        get
        {
            Expression<Func<MessageLogRecord, bool>> expr = x => 
                x.ResponseDate == NullDate; //todo: test if this works or if I have to define the value within the expression
            return expr;
        }
    }
}
+2
1

# 1 - EF Linq to Entities. , EF , , , . - SQL - , .

, : http://www.albahari.com/nutshell/predicatebuilder.aspx

public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T>()
  {
    return (Expression<Func<T, bool>>) (input => true);
  }

  public static Expression<Func<T, bool>> False<T>()
  {
    return (Expression<Func<T, bool>>) (input => false);
  }

  public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
  {
    InvocationExpression invocationExpression = Expression.Invoke((Expression) expression2, expression1.Parameters.Cast<Expression>());
    return Expression.Lambda<Func<T, bool>>((Expression) Expression.OrElse(expression1.Body, (Expression) invocationExpression), (IEnumerable<ParameterExpression>) expression1.Parameters);
  }

  public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
  {
    InvocationExpression invocationExpression = Expression.Invoke((Expression) expression2, expression1.Parameters.Cast<Expression>());
    return Expression.Lambda<Func<T, bool>>((Expression) Expression.AndAlso(expression1.Body, (Expression) invocationExpression), (IEnumerable<ParameterExpression>) expression1.Parameters);
  }
}

, . PredicateBuilder.True<YourEntityHere>().And(... expression1 ...).And(...)..., OR, , false: PredicateBuilder.False<YourEntityHere>().Or(...)...

, Q3 :

public static Expression<Func<MessageLogRecord, bool>> MessageIsPendingResponse
{
    get
    {
        Expression<Func<CCI_Int_ExportLog, bool>> expr = PredicateBuilder.True<MessageLogRecord>()
            .And(MessageIsProcessed)
            .And(MessageIsInbound)
            .And(ResponseNotYetSent)
        ;
        return expr;
    }
}
+4

Source: https://habr.com/ru/post/1766318/


All Articles