首页 > 解决方案 > 解析表达式树

问题描述

我想使用 LINQ 表达式作为方法参数来构建 Dapper 字符串。我在 MS Docs 找到了一个解析示例并将其集成到我的代码中:

public static List<Notification> GetNotifs(Expression<Func<Notification, bool>> p)
        {
            using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
            {
                string sqlQ = "SELECT * FROM Notifications WHERE ";
                ParameterExpression param = p.Parameters[0];
                BinaryExpression operation = (BinaryExpression)p.Body;
                ParameterExpression left = (ParameterExpression)operation.Left;
                for (int i = 0; i < left.Name.Length; i++) { if (i <= param.Name.Length) { } else { sqlQ += left.Name[i]; } }
                ConstantExpression right = (ConstantExpression)operation.Right;
                if (operation.NodeType.ToString() == "LessThan") sqlQ += " <";
                else if (operation.NodeType.ToString() == "GreaterThan") sqlQ += " >";
                else if (operation.NodeType.ToString() == "LessThanOrEqual") sqlQ += " <=";
                else if (operation.NodeType.ToString() == "GreaterThanOrEqual") sqlQ += " >=";
                else if (operation.NodeType.ToString() == "Equal") sqlQ += " =";
                else if (operation.NodeType.ToString() == "NotEqual") sqlQ += " !=";
                sqlQ += " " + right.Value;
                return connection.Query<Notification>(sqlQ).ToList();
            }
        }

但是,不幸的是,它在

ParameterExpression left = (ParameterExpression)operation.Left;

这个方法的调用是这样的:

DRepository.GetNotifs(uid => uid.U_Id == id)

你能帮我找出来,我在哪里不正确?

标签: c#parsinglambdaexpression

解决方案


下面的示例生成 SQL SELECT * FROM Notifications WHERE U_Id = 1

[Test]
public void DapperExpression()
{
    // Arrange
    var id = 1;

    // Act
    var list = GetNotifs(uid => uid.U_Id == id);

    // Assert 
    Assert.IsNotEmpty(list);
}

public static List<Notification> GetNotifs(Expression<Func<Notification, bool>> p)
{
    using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
    {
        string sqlQ = "SELECT * FROM Notifications WHERE ";
        ParameterExpression param = p.Parameters[0];
        BinaryExpression operation = (BinaryExpression)p.Body;
        var t = operation.Left.GetType();
        MemberExpression left = (MemberExpression)operation.Left;
        sqlQ += left.Member.Name;
        MemberExpression right = (MemberExpression)operation.Right;
        ConstantExpression cnst = (ConstantExpression) right.Expression;
        var field = cnst.Type.GetFields().Single();
        var val = field.GetValue(cnst.Value);

        if (operation.NodeType.ToString() == "LessThan") sqlQ += " <";
        else if (operation.NodeType.ToString() == "GreaterThan") sqlQ += " >";
        else if (operation.NodeType.ToString() == "LessThanOrEqual") sqlQ += " <=";
        else if (operation.NodeType.ToString() == "GreaterThanOrEqual") sqlQ += " >=";
        else if (operation.NodeType.ToString() == "Equal") sqlQ += " =";
        else if (operation.NodeType.ToString() == "NotEqual") sqlQ += " !=";
        sqlQ += " " + val;

        return connection.Query<Notification>(sqlQ).ToList();
    }
}

请注意,它会在int. string例如,您应该添加一些类型相关的逻辑来添加引用Guid。您可以从field变量中获取此类型。希望能帮助到你。


推荐阅读