Это - мой запрос:
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)
В настоящее время Соединению не оставляют соединение, означая, не имеет ли некоторый форум сообщения, которое принадлежит ему, это не будет возвращено.
Форум без сообщений должен быть возвращен с пустым указателем (или значение по умолчанию) значения для свойств сообщения.
ОБНОВЛЕНИЕ
Набор результатов должен быть некоторой подобной вещью:
ForumId | ForumTitle | LastPostTitle | LastPostAddedDate
--------+------------+---------------+------------------
4 | Sport | blabla | 12/4/2010
4 | Sport | blabla | 15/4/2010
6 | Games | blabla | 1/5/2010
7 | Flame | |
Вот код, который поможет вам отработать левое соединение с помощью ссылки
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);
}
}
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
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)
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.