EntityFramework NotSupportedException使用嵌入式Join加入

时间:2014-08-09 17:34:55

标签: c# linq entity-framework

由于某种原因,下面的代码会出现此错误:

  

类型' System.NotSupportedException'的例外情况发生在EntityFramework.SqlServer.dll中但未在用户代码中处理

     

其他信息:LINQ to Entities无法识别该方法   ' {System.Linq.IQueryable {1}} 1 [System.Func`2 [DansBlog.Domain.BlogEntities.Post,System.Boolean]])'   方法,并且此方法无法转换为商店表达式。

代码:

1[DansBlog.Domain.BlogEntities.Post]
  Retrieve(System.Linq.Expressions.Expression

1 个答案:

答案 0 :(得分:1)

LINQ to Entities不支持对postRepository.Retrieve的子调用。 为了实现这一目标,您需要使用GroupJoin方法重新构建查询并在查询中提取Posts集合,并使用匿名类型将Posts与Blog结合使用。 生成的查询结构应如下所示:

var allResult = blogRepository.Retrieve()
               .Join(userRepository.Retrieve(), b => b.UserId, u => u.Id, (blog, user) => new { blog, user})
               .GroupJoin(postRepository.Retrieve(), 
                                     .GroupJoin(userRepository.Retrieve(), p => p.UserId, pu => pu.Id, 
                                        (post, authors) => new GUI.Models.Blogging.Post()
                                        {
                                            Id = post.Id,
                                            BlogId = post.BlogId,
                                            User = authors.Select(pa => new GUI.Models.Blogging.User()
                                            {
                                                UserId = pa.Id,
                                                UserName = pa.UserName,
                                                // etc
                                            }).FirstOrDefault()
                                        }),
                      blogData => blogData.blog.Id, p => p.BlogId, (blogData, posts) => new { blogData, posts })
                 .Select(projection => new GUI.Models.Blogging.Blog()
                 {
                    Id = projection.blogData.blog.Id,
                    // etc
                    User = new GUI.Models.Blogging.User()
                    {
                        UserId = projection.blogData.user.Id,
                        UserName = projection.blogData.user.UserName,
                        // etc
                    },
                    Posts =  projection.posts
                 }
             );

请注意,使用Method语法编写的LINQ查询并不像第一眼看上去那样可读。如果可能的话,请考虑使用Query syntax(如果没有,请回退到Method),因为它可以提高可读性并使您的代码在大多数情况下更加清晰。例如,上面的查询看起来像:

var allResult = from blog in blogRepository.Retrieve()
                join user in userRepository.Retrieve() on b.UserId equals u.Id
                join p in postRepository.Retrieve()
                                        .GroupJoin(userRepository.Retrieve(), p => p.UserId, pu => pu.Id, 
                                            (post, authors) => new GUI.Models.Blogging.Post()
                                            {
                                                Id = post.Id,
                                                BlogId = post.BlogId,
                                                User = (from pu in authors
                                                        select new GUI.Models.Blogging.User()
                                                        {
                                                            UserId = pu.Id,
                                                            UserName = pu.UserName,
                                                            // etc
                                                        }).FirstOrDefault()
                                            }),
                          on blog.Id equals p.BlogId into posts
                 select new GUI.Models.Blogging.Blog()
                     {
                        Id = blog.Id,
                        // etc
                        User = new GUI.Models.Blogging.User()
                        {
                            UserId = user.Id,
                            UserName = user.UserName,
                            // etc
                        },
                        Posts = posts
                     }
                 );