我一直找不到任何示例,可以在LINQ的选择投影中根据变量有条件地排除字段,请参见LINQ: Select an object and change some properties without creating a new object。
让我就我要实现的目标提供一些背景知识。我想根据用户是否可以编辑数据来限制从模型设置的DTO中的某些字段(即注释字段)。例如,以下选择了一个名为CustomerView的委托。
var qry = _ctx.Customer.Select(CustomerView(User.IsInRole("Editor")));
Customer模型具有Orders导航属性,以下函数将数据转换为CusomerViewModel DTO。
private Expression<Func<Customer, CustomerViewModel>> CustomerView(bool isEditor) {
return c => new CustomerViewModel
{
Id = c.Id,
Name = c.Name,
Comment = isEditor ? c.Comment : null,
OrderCount = c.Orders.Count()
};
}
这将生成像CASE WHEN @__isEditor_0 = TRUE THEN Comment ELSE NULL
这样的SQL,该SQL可以工作,但是我更希望甚至不生成该表达式,即默认保留字段。那是一个简单的用例,但是如果我想对OrderCount字段做同样的事情,SQL子查询仍然会包含在内。
我当然可以为非编辑者用户创建另一个函数,该函数排除某些字段,但是我宁愿没有单独的投影来维护,尤其是当它们更复杂时。
我看到了一些疑问,其中动态LINQ用于where子句,但对于select没有那么多。这种方法可行吗?
编辑:使用选择后,是否可以通过扩展方法手动从表达式树中删除字段?
答案 0 :(得分:0)
使用LINQKit可以通过添加AsExpandable()
进行选择来达到预期的效果。
var qry = _ctx.Customer.AsExpandable().Select(CustomerView(User.IsInRole("Editor")));
然后为注释字段添加表达式,并在字段分配上调用Invoke()
。
private Expression<Func<Customer, CustomerViewModel>> CustomerView(bool isEditor) {
Expression<Func<Customer, string>> exprComment;
if (isEditor)
exprComment = c => c.Comment;
else
exprComment = c => null;
return c => new CustomerViewModel
{
Id = c.Id,
Name = c.Name,
Comment = exprComment.Invoke(c),
OrderCount = c.Orders.Count()
};
}
它看起来确实有效,但是我仍然想听听其他方法。