Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在带有EF4(和LINQKit)的Linq中使用外部表达式?_Linq_Entity Framework_Linq To Entities_Lambda - Fatal编程技术网

如何在带有EF4(和LINQKit)的Linq中使用外部表达式?

如何在带有EF4(和LINQKit)的Linq中使用外部表达式?,linq,entity-framework,linq-to-entities,lambda,Linq,Entity Framework,Linq To Entities,Lambda,我想分离出linq查询中经常使用的表达式。我正在使用EntityFramework4和LINQKit,但我仍然不知道应该如何正确使用它。让我举个例子: Article article = dataContainer.Articles.FirstOrDefault(a => a.Id == id); IEnumerable<Comment> comments = (from c in article.Comments where CommentExpressions.

我想分离出linq查询中经常使用的表达式。我正在使用EntityFramework4和LINQKit,但我仍然不知道应该如何正确使用它。让我举个例子:

Article article = dataContainer.Articles.FirstOrDefault(a => a.Id == id);

IEnumerable<Comment> comments =
  (from c in article.Comments
   where CommentExpressions.IsApproved.Invoke(c)
   select c);


public static class CommentExpressions
{
    public static Expression<Func<Comment, bool>> IsApproved
    {
        get
        {
            return c => c.IsApproved;
        }
    }
}
Article-Article=dataContainer.Articles.FirstOrDefault(a=>a.Id==Id);
数不清的评论=
(摘自第条c,评论)
其中CommentExpressions.IsApproved.Invoke(c)
选择c);
公共静态类表达式
{
公共静态表达式已被批准
{
得到
{
返回c=>c.IsApproved;
}
}
}
当然,被认可的表达方式要复杂得多

问题是Invoke()无法工作,因为我没有从container.Comments上的LINQKit调用.asExpandable(),但我无法调用它,因为它只是一个ICollection,而不是一个ObjectSet

所以我的问题是:当我想要包含外部表达式时,我是否总是需要遍历数据上下文,或者我是否可以在我获取的对象(文章)上使用它

有什么想法或最佳实践吗? 非常感谢!
neo

在使用LinqKit时,请使用谓词生成器:

IEnumerable<Comment> comments =
  article.Comments.Where(CommentExpressions.IsApproved).Select(c=>c);

 public static class CommentExpressions
 {
    public static Expression<Func<Module, bool>> IsApproved
    {
        get
        {
            var pred = PredicateBuilder.True<Module>();
            pred = pred.And(m => m.IsApproved);
            return pred
        }
    }
 }
IEnumerable注释=
article.Comments.Where(CommentExpressions.IsApproved)。选择(c=>c);
公共静态类表达式
{
公共静态表达式已被批准
{
得到
{
var pred=PredicateBuilder.True();
pred=pred.和(m=>m.已批准);
返回pred
}
}
}

问题是EF不支持调用表达式,因此需要以不同的方式将表达式折叠到EF中

你应该看看Damien的帖子,它基本上满足了你的要求

有关更多背景信息,请查看科林·米克(Colin Meek)关于如何访问和替换的帖子

希望这有帮助


亚历克斯

我想我找到了我“问题”的答案。我的问题不是真正的问题,而是一种错误的思维方式

当我通读时,我清楚地意识到我只是想为一个错误的问题找到一个解决方案。让我解释一下

我将POCO模板与EF4一起使用,并且延迟加载仍然处于激活状态。有了它,我可以神奇地遍历对象而不发送额外的查询,至少它们在我的代码中不可见。但当然,对于对关系的每次访问,都会发送查询,我还使用EF Profiler观察了这些查询。当然,我也想让它们以最佳方式运行,即“在sql中使用where条件”,而不是“获取所有行,然后进行过滤”。这种思维方式也称为过早优化

当我开始思考“如果我不使用延迟加载,会是什么样子?”时,我终于想到了这一点。很简单,我想要的所有数据都是在第一时间获取的,之后你只对这些数据进行操作,而不对任何其他数据进行操作,也就是说,没有隐藏的查询。从这个角度来看,在域对象的关系上使用ICollection而不是IQueryable是有意义的。当然,对于ICollection的.Where()调用,我不能使用表达式>,而是使用内部函数

为了回答我自己的问题,表达式只能在访问存储库或知道哪些POCO对象不是存储库时使用。如果它们应该在外部使用,即在ICollection上使用,则必须将它们编译为Func对象,如下所示:

IEnumerable<Comment> comments =
  (from c in article.Comments
   select c).Where(CommentExpressions.IsApproved.Compile());
IEnumerable<Comment> comments =
  (from c in dataContainer.ArticleComments
   where c.ArticleId == article.Id
   select c).Where(CommentExpressions.IsApproved);
IEnumerable注释=
(摘自第条c,评论)
选择c).其中(CommentExpressions.IsApproved.Compile());
如果确实需要高性能,则必须要求存储库通过匹配ID和满足CommentExpressions.IsApproved的位置来获取属于该文章的所有注释。诸如此类:

IEnumerable<Comment> comments =
  (from c in article.Comments
   select c).Where(CommentExpressions.IsApproved.Compile());
IEnumerable<Comment> comments =
  (from c in dataContainer.ArticleComments
   where c.ArticleId == article.Id
   select c).Where(CommentExpressions.IsApproved);
IEnumerable注释=
(来自dataContainer.ArticleComments中的c)
其中c.ArticleId==article.Id
选择c).其中(CommentExpressions.IsApproved);
现在,由于缺少.compile(),最后一个where条件保留了一个表达式,可以在sql中使用

我对此几乎满意。我感到恼火的是需要调用“.compile()”,而我仍然不明白的是,我应该如何构造或让一个表达式使用另一个表达式,这似乎是不可能的,除非在包含它的同时调用.compile(),因为这也是我无法放置表达式对象的唯一ICollection。我想在这里我可以使用LINQKit,然后去掉compile()调用


我希望我的方向是正确的。如果您发现了任何逻辑错误或可以想出更好的方法,请在评论中告诉我,以便我可以更新答案。谢谢大家

您的示例代码第4行的“article.Comments”而不是“container.Comments”是指“article.Comments”吗?哦,是的,谢谢,我更正了它对我不起作用,因为article.Comments.Where()只接受Func而不接受表达式。(还有一个输入错误,不是“模块,布尔”,而是“评论,布尔”,对不起)嗯。。。Damien的帖子依赖于将“.WithTranslations()”放在表达式末尾,但在我的例子中,这同样是不可能的,因为在获取文章对象之后,我没有得到IQueryable的,例如,对于Article.Comments和as.WithTranslations是IQueryable的扩展,这没有帮助。如果我忽略了什么,告诉我。