根据我之前的问题:Pulling Apart Expression<Func<T, object>>
- 我正试图让它更先进一点。目前,我可以这样做:
var matchingPeople = Connection.Get<Person>(p => p.MarketId == marketId);
它将被转换为DapperExtensionsFieldPredicate
:
// Assume I've successfully parsed p => p.MarketId == marketId into its constituent parts:
// left = p => p.MarketId, theOperator = Operator.Eq, right = marketId
Predicates.Field(left, theOperator, right);
我现在希望能够做到这一点:
var matchingPeople = Connection.Get<Person>(p => p.MarketId == marketId && p.FirstName == "John" || p.FirstName == "Jack");
并生成如下所示的 SQL:
DECLARE @MarketId INT = 3
DECLARE @FirstName01 VARCHAR(MAX) = 'John'
DECLARE @FirstName02 VARCHAR(MAX) = 'Jack'
SELECT *
FROM Person
WHERE MarketId = @MarketId AND (FirstName = @FirstName01 OR FirstName = @FirstName02)
通过使用DapperExtensionsCompound Predicate Groups
:
// ** This is the code I am trying to dynamically create based on the lambda that is passed in **
var predicateGroupAnd = new PredicateGroup {Operator = GroupOperator.And, Predicates = new List<IPredicate>()};
// I already have the code to determine: left = p => p.MarketId, theOperator = Operator.Eq, right = marketId
predicateGroupAnd.Predicates.Add(Predicates.Field(left, Operator.Eq, right));
var predicateGroupOr = new PredicateGroup {Operator = GroupOperator.Or, Predicates = new List<IPredicate>()};
// I already have the code to determine: left = p => p.FirstName, theOperator = Operator.Eq, right = "John"
predicateGroupAnd.Predicates.Add(Predicates.Field(left, Operator.Eq, right));
// I already have the code to determine: left = p => p.FirstName, theOperator = Operator.Eq, right = "Jack"
predicateGroupOr.Predicates.Add(Predicates.Field(left, Operator.Eq, right));
var predicateGroupAll = new PredicateGroup // This is what will be passed to DapperExtensions' GetList<T> method
{
Operator = GroupOperator.And, // How do I set this correctly?
Predicates = new List<IPredicate> {predicateGroupAnd, predicateGroupOr}
};
我的问题似乎与解析表达式树的方式有关。假设我们有 lambda 表达式:
p => p.MarketId == marketId && p.FirstName == "John" || p.FirstName == "Jack"
我可以将其转换为BinaryExpression
. 如果我使用BinaryExpression.Left
,我会得到
p.MarketId == marketId && p.FirstName == "John"
和BinaryExpression.Right
产量:
p.FirstName == "Jack"
此外,NodeType
整体的BinaryExpression
似乎设置为 lambda 的最后一个条件运算符,即ExpressionType.OrElse
我觉得我需要使用递归并从右到左遍历 lambda 表达式,但我无法创建我想要的复合组谓词。具体来说,我如何将AND
lambdas 组合在一起,以及OR
lambdas 组合在一起?谢谢!