Linq-to-Entities Left JOIN - PullRequest
       18

Linq-to-Entities Left JOIN

7 голосов
/ 05 мая 2010

Это мой запрос:

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) 

В настоящее время присоединение не оставлено присоединением, то есть если на каком-либо форуме нет сообщения, которое ему принадлежит, оно не будет возвращено.
Форум без сообщений должен быть возвращен со значениями NULL (или по умолчанию) для свойств сообщений.

ОБНОВЛЕНИЕ

Результирующий набор должен выглядеть примерно так:

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

Ответы [ 7 ]

1 голос
/ 25 апреля 2012

если не ошибка:

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)
1 голос
/ 14 марта 2013

Вы пробовали что-то вроде:

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
}
1 голос
/ 05 октября 2010

Попробуйте что-то вроде этого:

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)

свойства, которые возвращаются пустыми из левого соединения, также должны иметь значение null. Так int => int? и DateTime => DateTime? и т.д ..

1 голос
/ 19 августа 2010
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.

1 голос
/ 06 мая 2010

Вот код, который поможет вам разобраться в 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);
        }
    }
1 голос
/ 05 мая 2010
 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)  
0 голосов
/ 05 мая 2010
 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...