我正在重构一些代码,试图使其更加自说明。当前的代码有一个针对OData服务的查询,它看起来像这样:
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))
);
我希望使用Linq表达式来改变这个功能。
我可以将所有逻辑移动到单个表达式中,并运行代码context.MessageLog.Where(MessageIsPendingResponse);
。
但是,我想为不同的条件创建表达式:MessageIsProcessed
(即现在处于成功或失败状态),MessageIsInbound
和ResponseNotYetSent
(响应日期为空)。
我可以像下面这样将它们与多个where语句结合起来:
return context.MessageLog
.Where(MessageLogExpression.MessageIsProcessed)
.Where(MessageLogExpression.MessageIsInbound)
.Where(MessageLogExpression.ResponseNotYetSent);
(MessageLogExpression
是我用来包含这些预定义表达式的类).
问题1
这是合并语句的最佳方式吗?还是它可能会先过滤错误的字段(例如,Linq将所有条件组合成一个查询,并允许查询引擎(在SQL术语中)确定最佳执行计划;或者我们强制其首先在状态字段上进行过滤)?
问题2
上述内容非常适用于我们的表达式使用 AND 连接的场景; 但如果我们要使用 OR 怎么办? 我想有一些方法可以将它们组合起来,但找不到任何明显的东西。我怀疑是否存在类似于此的东西?
return context.MessageLog.Where(new OrExpression(MessageIsSuccess,MessageIsFailure));
问题三
有没有一种好的方法可以在另一个表达式定义中组合表达式,例如下面的代码(只是可以编译的版本)?
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;
}
}
}