重用 Linq to Entities表达式在“选择”和“调用地点”中

发布于 2024-08-25 17:00:21 字数 1578 浏览 3 评论 0 原文

假设我有一个实体对象定义为

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)
    }; 

,但它也不起作用。

关于如何让它发挥作用有什么想法吗?或者,如果不可能,那么在这两个地方重用业务逻辑的替代方案是什么?

谢谢

佩德罗

Suppose I have an entity object defined as

public partial class Article  
{  
    public Id
    {
        get;
        set;
    }  
    public Text
    {
        get;
        set;
    }  
    public UserId
    {
        get;
        set;
    }  
}

Based on some properties of an Article, I need to determine if the article can be deleted by a given user. So I add a static method to do the checking. Something like:

public partial class Article  
{  
    public static Expression<Func<Article, bool>> CanBeDeletedBy(int userId)
    {  
        //Add logic to be reused here
        return a => a.UserId == userId;
    }  
}

So now I can do

using(MyEntities e = new MyEntities())  
{
    //get the current user id
    int currentUserId = 0;

    e.Articles.Where(Article.CanBeDeletedBy(currentUserid));  
}

So far so good. Now I want to reuse the logic in CanBeDeletedBy while doing a Select, something like:

using(MyEntities e = new MyEntities())  
{
    //get the current user id
    int currentUserId = 0;

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = ???  
    };  
}

But no matter what I try, I can't use the expression in the select method. I guess that If I can do

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = a => a.UserId == userId
    };  

Then I should be able to use the same expression. Tried to compile the expression and call it by doing

    e.Articles.Select(a => new  
    {  
        Text = a.Text,  
        CanBeDeleted = Article.CanBeDeletedBy(currentUserId).Compile()(a)
    }; 

but it won't work either.

Any ideas on how to get this to work? Or if it isn't possible, what are the alternatives to reuse business logic in both places?

Thanks

Pedro

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千柳 2024-09-01 17:00:21

重复使用表达式树是一门黑术;你可以做到这一点,但你需要将大量代码切换到反射,并且你会失去所有静态检查。特别是,使用匿名类型变成了一场噩梦(尽管 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?

流绪微梦 2024-09-01 17:00:21

我所做的是使用 PredicateBuilder,它是 LinqKit 中的一个类,也是 AsExpandable() http://www .albahari.com/nutshell/linqkit.aspx 来构建表达式,我将它们静态存储

public readonly Expression<Func<T,bool>>

在静态类中。每个表达式都建立在前一个表达式的基础上,从而减少了重复量。

正如 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

public readonly Expression<Func<T,bool>>

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文