繁体   English   中英

Linq-to-Entities离开JOIN

[英]Linq-to-Entities Left 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属性的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 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
}
 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<EntityRole> GetSourceEntityRole()
    {
        var list = new List<EntityRole>() {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<EntityRole> GetEmptyEntityRole()
    {
        var list = new List<EntityRole>();

        return list;
    }

    public void TestToDelete()
    {
        var source = this.GetSourceEntityRole();
        var destination = this.GetEmptyEntityRole();

        this.TestLeftJoin(source, destination);
    }

    private void TestLeftJoin(IList<EntityRole> source, IList<EntityRole> 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<EntityRole> GetMissing(IList<EntityRole> sourceEntities, IList<EntityRole> 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<EntityRole> 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? 等等..

 public class ForumPosts 
    {
        public Forum Forum { get; set; }
        public IQueryable<Post> 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<DisplaySet> ds = new List<DisplaySet>();

                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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM