c# - 解析表达式树
问题描述
我想使用 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)
你能帮我找出来,我在哪里不正确?
解决方案
下面的示例生成 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
变量中获取此类型。希望能帮助到你。
推荐阅读
- vue.js - 使用类绑定时未显示 Vue 错误页面
- python - QTreeView 拖放:QAbstractItemView.InternalMove 允许拖放外部视图?
- ios - 用户选择后应用跟踪透明度重置
- python - 序数编码:如何对满足特定条件的值进行编码?
- java - Mkdir() 在 Android Realme 设备中不起作用?
- c++ - C ++设置允许重复?
- python - 如何在 spyder anaconda 中安装 arcpy
- java - 注释处理不适用于 lombok 和 java
- arrays - 如何从文本文件创建多个数组并循环遍历每个数组的值
- c++ - 何时应在 std::unordered_map/std::unordered_set 上使用 std::map/std::set?