[英]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.