重用 Linq to Entities表达式在“选择”和“调用地点”中
假设我有一个实体对象定义为
public partial class Article
{
public Id
{
get;
set;
}
public Text
{
get;
set;
}
public UserId
{
get;
set;
}
}
基于文章的某些属性,我需要确定给定用户是否可以删除该文章。所以我添加了一个静态方法来进行检查。比如:
public partial class Article
{
public static Expression<Func<Article, bool>> CanBeDeletedBy(int userId)
{
//Add logic to be reused here
return a => a.UserId == userId;
}
}
所以现在我可以做得
using(MyEntities e = new MyEntities())
{
//get the current user id
int currentUserId = 0;
e.Articles.Where(Article.CanBeDeletedBy(currentUserid));
}
很好。现在我想在执行 Select 时重用 CanBeDeletedBy 中的逻辑,例如:
using(MyEntities e = new MyEntities())
{
//get the current user id
int currentUserId = 0;
e.Articles.Select(a => new
{
Text = a.Text,
CanBeDeleted = ???
};
}
但无论我尝试什么,我都无法使用 select 方法中的表达式。我想如果我能做到
e.Articles.Select(a => new
{
Text = a.Text,
CanBeDeleted = a => a.UserId == userId
};
那么我应该能够使用相同的表达方式。尝试编译表达式并通过执行调用它
e.Articles.Select(a => new
{
Text = a.Text,
CanBeDeleted = Article.CanBeDeletedBy(currentUserId).Compile()(a)
};
,但它也不起作用。
关于如何让它发挥作用有什么想法吗?或者,如果不可能,那么在这两个地方重用业务逻辑的替代方案是什么?
谢谢
佩德罗
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
重复使用表达式树是一门黑术;你可以做到这一点,但你需要将大量代码切换到反射,并且你会失去所有静态检查。特别是,使用匿名类型变成了一场噩梦(尽管 4.0 中的
dynamic
可能是可行的)。此外,如果您作弊并使用
Expression.Invoke
,则并非所有提供程序都支持它(最明显的是 .NET 3.5SP1 中的 EF 不支持)。除非这是一个主要的痛点,否则我会保留重复的内容。或者您需要重新使用表达式树?
Re-using expression trees is a black art; you can do it, but you would need to switch a lot of code to reflection and you'd lose all the static checking. In particular, working with the anonymous types becomes a nightmare (although
dynamic
in 4.0 might be workable).Further, if you cheat and use
Expression.Invoke
, then it isn't supported by all providers (most noticeably not on EF in .NET 3.5SP1).Unless this is a major pain point, I'd leave it with duplication. Or do you need to re-use the expression tree?
我所做的是使用 PredicateBuilder,它是 LinqKit 中的一个类,也是 AsExpandable() http://www .albahari.com/nutshell/linqkit.aspx 来构建表达式,我将它们静态存储
在静态类中。每个表达式都建立在前一个表达式的基础上,从而减少了重复量。
正如 Marc Gravell 提出的上一个问题所暗示的那样,这种事情是一种黑魔法,但值得庆幸的是,很多工作都是由其他人完成的。
What I did is I used PredicateBuilder which is a class in LinqKit and also AsExpandable() http://www.albahari.com/nutshell/linqkit.aspx to build up expressions and I stored them Statically as
in a static class. Each expression was building on a previous expression thus reducing the amount of duplication.
As the previous question by Marc Gravell suggests this kinda thing is a black art, but thankfully a lot of the work has been done by other poeple.