使用 LINQ select 有条件地忽略字段
Conditionally ignore fields with LINQ select
我一直找不到任何示例,您可以在这些示例中根据 LINQ 中的 select 投影中的变量有条件地排除字段,另请参阅 LINQ: Select an object and change some properties without creating a new object。
让我介绍一下我要实现的目标的背景知识。我想根据用户是否可以编辑数据(即评论字段)来限制从模型中设置的 DTO 中的某些字段。例如,以下 select 具有名为 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()
};
}
这将生成 SQL,就像 CASE WHEN @__isEditor_0 = TRUE THEN Comment ELSE NULL
一样有效,但我更希望表达式甚至不生成,即字段保留为默认值。这是一个简单的用例,但如果我想对 OrderCount 字段执行相同的操作,SQL 子查询仍会包含在内。
当然,我可以为非编辑器用户创建另一个排除某些字段的函数,但我宁愿没有单独的预测来维护,尤其是当它们更复杂时。
我看到动态 LINQ 用于 where 子句但没有那么多用于 select 的问题。这种做法可行吗?
编辑:在使用 select 之后,是否可以通过扩展方法从表达式树中手动删除字段?
使用 LINQKit 我能够通过将 AsExpandable()
添加到 select 来实现预期的结果。
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()
};
}
它确实有效,但我仍然有兴趣了解任何替代方法。
我一直找不到任何示例,您可以在这些示例中根据 LINQ 中的 select 投影中的变量有条件地排除字段,另请参阅 LINQ: Select an object and change some properties without creating a new object。
让我介绍一下我要实现的目标的背景知识。我想根据用户是否可以编辑数据(即评论字段)来限制从模型中设置的 DTO 中的某些字段。例如,以下 select 具有名为 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()
};
}
这将生成 SQL,就像 CASE WHEN @__isEditor_0 = TRUE THEN Comment ELSE NULL
一样有效,但我更希望表达式甚至不生成,即字段保留为默认值。这是一个简单的用例,但如果我想对 OrderCount 字段执行相同的操作,SQL 子查询仍会包含在内。
当然,我可以为非编辑器用户创建另一个排除某些字段的函数,但我宁愿没有单独的预测来维护,尤其是当它们更复杂时。
我看到动态 LINQ 用于 where 子句但没有那么多用于 select 的问题。这种做法可行吗?
编辑:在使用 select 之后,是否可以通过扩展方法从表达式树中手动删除字段?
使用 LINQKit 我能够通过将 AsExpandable()
添加到 select 来实现预期的结果。
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()
};
}
它确实有效,但我仍然有兴趣了解任何替代方法。