Linq-to-Entities离开JOIN

这是我的查询:

from forum in Forums join post in Posts on forum equals post.Forum into postGroup from p in postGroup where p.ParentPostID==0 select new { forum.Title, forum.ForumID, LastPostTitle = p.Title, LastPostAddedDate = p.AddedDate }).OrderBy(o=>o.ForumID) 

目前,Join不是左连接,这意味着如果某个论坛没有属于它的post,则不会返回。
没有post的论坛必须返回post属性的null(或默认)值。

UPDATE

结果集应该是这样的:

 ForumId | ForumTitle | LastPostTitle | LastPostAddedDate --------+------------+---------------+------------------ 4 | Sport | blabla | 12/4/2010 4 | Sport | blabla | 15/4/2010 6 | Games | blabla | 1/5/2010 7 | Flame | | 

  var allforums = from f in context.Fora.Include("Posts") select f; 

此查询产生的结果与

  var allForums = from f in context.Fora select new ForumPosts { Forum = f, Posts = context.Posts.Where(x=> x.ForumId == f.ForumId) 

这里有一些代码可以帮助你解决Left Join with Link问题

  private class EntityRole { public int EntityId { get; set; } public int RoleId { get; set; } } private IList GetSourceEntityRole() { var list = new List() {new EntityRole(){EntityId = 123, RoleId = 1}, new EntityRole(){EntityId = 123, RoleId = 2}, new EntityRole(){EntityId = 123, RoleId = 3}, new EntityRole(){EntityId = 123, RoleId = 4}}; list.Reverse(); return list; } private IList GetEmptyEntityRole() { var list = new List(); return list; } public void TestToDelete() { var source = this.GetSourceEntityRole(); var destination = this.GetEmptyEntityRole(); this.TestLeftJoin(source, destination); } private void TestLeftJoin(IList source, IList destination) { var inserting = this.GetMissing(source, destination); var deleting = this.GetMissing(destination, source); this.Enumerate("Source", source); this.Enumerate("Destination", destination); this.Enumerate("Deleting", deleting); this.Enumerate("Inserting", inserting); } private IEnumerable GetMissing(IList sourceEntities, IList destinationEntities) { return from source in sourceEntities join dest in destinationEntities on source.RoleId equals dest.RoleId into joined from source2 in joined.DefaultIfEmpty() where source2 == null select source; } private void Enumerate(string source, IEnumerable roles) { foreach (var item in roles) { Console.WriteLine("{0}:{1}", source, item.RoleId); } } 
 Forums .GroupJoin(PostGroup, f => f.ID, p => p.ForumID, (f, p) => new { Forum = f, PostList = p }) .Where(anon => anon.PostList.Any(pl => pl.ParentPostID.Equals(0))) .OrderBy(anon => anon.Forum.ForumID) .Select(anon => new { Title = anon.Forum.Title, ForumID = anon.Forum.ForumID, LastPostTitle = anon.PostList.FirstOrDefault().Title, LastPostAddedDate = anon.PostList.FirstOrDefault().AddedDate, }); 

类似的东西。 我不太确定,因为我没有真正的数据模型视图,但GroupJoin应该非常类似于LEFT OUTER JOIN,即使它在SQL中没有实际产生。

尝试这样的事情:

 from forum in Forums join post in Posts on forum equals post.Forum into postGroup // from p in postGroup // where p.ParentPostID==0 select new { forum.Title, forum.ForumID, LastPostTitle = postGroup.FirstOrDefault(p => p.ParentPostID==0).Title, LastPostAddedDate = (DateTime?)postGroup.FirstOrDefault(p => p.ParentPostID==0).AddedDate }).OrderBy(o=>o.ForumID) 

从左连接返回空的属性也必须是可空的。 那么int => int? 和DateTime => DateTime? 等等..

如果没有错误:

 var list = from forum in Forums.DefaultItIfEmpty() from post in Posts.DefaultItIfEmpty() where forum.forum_id == post.forum_id && post.ParentPostID==0 select new { forum.Title, forum.ForumID, LastPostTitle = p.Title, LastPostAddedDate = p.AddedDate }).OrderBy(o=>o.ForumID) 

你尝试过这样的事情:

 from forum in Forums from posts in (Posts.Where(qPosts=> forum.ForumId == qPosts.ForumId)).DefaultIfEmpty() where posts.ParentPostID == 0 orderby forum.ForumId select new { forum.Title, forum.ForumID, LastPostTitle = posts.Title, LastPostAddedDate = posts.AddedDate } 
  public class ForumPosts { public Forum Forum { get; set; } public IQueryable Posts { get; set; } } public class DisplaySet { public string Name { get; set; } public string PostTile { get; set; } } //left outer join using (ClassLibrary1.Entities context = new Entities()) { var allForums = from f in context.Fora select new ForumPosts { Forum = f, Posts = context.Posts.Where(x=> x.ForumId == f.ForumId) }; List ds = new List(); foreach (var forum in allForums) { if (forum.Posts.AsEnumerable().Count() != 0) { foreach (var post in forum.Posts) { ds.Add(new DisplaySet(){ Name = forum.Forum.Name, PostTile = post.PostValue}); } } else ds.Add(new DisplaySet(){ Name = forum.Forum.Name, PostTile = string.Empty}); } foreach (var item in ds) { Console.WriteLine(string.Format("{0} || {1}",item.Name,item.PostTile)); } } //This produces the following LINQ query which is right SELECT [Project1].[ForumId] AS [ForumId], [Project1].[Name] AS [Name], [Project1].[C1] AS [C1], [Project1].[PostId] AS [PostId], [Project1].[PostValue] AS [PostValue], [Project1].[ForumId1] AS [ForumId1] FROM ( SELECT [Extent1].[ForumId] AS [ForumId], [Extent1].[Name] AS [Name], [Extent2].[PostId] AS [PostId], [Extent2].[PostValue] AS [PostValue], [Extent2].[ForumId] AS [ForumId1], CASE WHEN ([Extent2].[PostId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] FROM [dbo].[Forum] AS [Extent1] LEFT OUTER JOIN [dbo].[Post] AS [Extent2] ON [Extent2].[ForumId] = [Extent1].[ForumId] ) AS [Project1] ORDER BY [Project1].[ForumId] ASC, [Project1].[C1] ASC