在我的特定场景中,我动态构建一个SQL语句来搜索记录。这发生在业务服务层的WebApi中的服务器端。现在我想扩展此功能,以便也可以在客户端设置WHERE
子句。我想使用强类型,这样我就不会在客户端硬编码列名。
到目前为止,我做了以下事情:
1)从INFORMATION_SCHEMA
获取视图的列并填充Dictionary<string, object>
,以便在稍后阶段设置列值。我可能会更改为自定义类,以便我可以添加比较器字段,而不只是column_name = column_value
。
2)我创建了一个自定义属性和一个只包含我想要向客户端公开的搜索列的类:
public class CustomerSearchDto
{
[SearchColumn(Name = "customer_type")]
public CustomerType CustomerType { get; set; }
[SearchColumn(Name = "city")]
public string City { get; set; }
public CustomerSearchDto()
{ }
}
3)所以在客户端,现在我可以做到:
//Following line is pseudo-code
var predicate = (x => x.CustomerType == CustomerType.Private);
如何获取这个lambda表达式,并从(1)获得列列表并知道(2)中的列名,设置字典中相应列的值?
答案 0 :(得分:0)
有太多的假设,但你可以从这样的事情开始:
static void SetValue<T>(Dictionary<string, object> target, Expression<Func<T, bool>> predicate)
{
var comparison = predicate.Body as BinaryExpression;
Debug.Assert(comparison != null);
var member = (comparison.Left.NodeType == ExpressionType.Convert ?
((UnaryExpression)comparison.Left).Operand :
comparison.Left) as MemberExpression;
Debug.Assert(member != null);
var value = comparison.Right as ConstantExpression;
Debug.Assert(value != null);
var attribute = Attribute.GetCustomAttribute(member.Member, typeof(SearchColumnAttribute)) as SearchColumnAttribute;
var columnName = attribute?.Name ?? member.Member.Name;
var columnValue = value.Value;
target[columnName] = columnValue;
}
测试:
Expression<Func<CustomerSearchDto, bool>> predicate = (x => x.CustomerType == CustomerType.Private);
var dict = new Dictionary<string, object>();
SetValue(dict, predicate);
答案 1 :(得分:0)
通过使用.footer-bottom {
margin-right: auto;
margin-left: auto;
padding-left: 0;
padding-right: 0;
background-color: #6ab3ac;
height: 100%;
line-height: 50px;
color: #fff;
}
重写字典,您可以在一步中从客户端表达式转换为SQL表达式,而不是构建字典然后构建查询。
您的ExpressionVisitor
会覆盖相应的方法,例如ExpressionVisitor
并在该方法中将客户端字段名称转换为服务器端字段名称。
您仍然存在序列化Expressions客户端并在服务器端反序列化的问题,但是一旦拥有它们,您可以使用访问者为SQL重写它们。