我试图弄清楚如何在LINQ中进行混合连接,并具有对2个LINQ对象的特定访问权限。以下是实际TSQL查询的外观示例:
SELECT
*
FROM
[User] AS [a]
INNER JOIN
[GroupUser] AS [b]
ON
[a].[UserID] = [b].[UserID]
INNER JOIN
[Group] AS [c]
ON
[b].[GroupID] = [c].[GroupID]
LEFT JOIN
[GroupEntries] AS [d]
ON
[a].[GroupID] = [d].[GroupID]
WHERE [a].[UserID] = @UserID
最后,基本上我想要的是一个充满GroupEntry对象的可枚举对象。感兴趣的是此查询中的最后两个表/对象。我将显示组作为组标题,以及组标题下的所有条目。如果组没有条目,我仍然希望将该组视为没有任何条目的标题。这是我到目前为止所做的:
因此,我想做一个功能:
public void DisplayEntriesByUser(int user_id)
{
MyDataContext db = new MyDataContext();
IEnumberable<GroupEntries> entries =
(
from user in db.Users
where user.UserID == user_id
join group_user in db.GroupUsers
on user.UserID = group_user.UserID
into a
from join1 in a
join group in db.Groups
on join1.GroupID equals group.GroupID
into b
from join2 in b
join entry in db.Entries.DefaultIfEmpty()
on join2.GroupID equals entry.GroupID
select entry
);
Group last_group_id = 0;
foreach(GroupEntry entry in entries)
{
if (last_group_id == 0 || entry.GroupID != last_group_id)
{
last_group_id = entry.GroupID;
System.Console.WriteLine("---{0}---", entry.Group.GroupName.ToString().ToUpper());
}
if (entry.EntryID)
{
System.Console.WriteLine(" {0}: {1}", entry.Title, entry.Text);
}
}
}
上面的示例并不像预期的那样有效。有两个问题我无法解决:
我似乎仍然在最后一次加入时获得INNER JOIN而不是LEFT JOIN。我没有得到任何空的结果,因此没有条目的组不会出现。
我需要弄清楚一种方法,以便我可以填写空白条目集的默认值。也就是说,如果有一个没有条目的组,我希望返回一个大部分空白的条目,除了我希望EntryID为null或0,GroupID是它所代表的空组的ID ,我需要一个entry.Group对象的句柄(即它的父对象,空组对象)。
对此的任何帮助将不胜感激。
注意:表名和真实世界的表示纯粹是为了这个例子而得到的,但它们之间的关系简化了我想要做的事情。
答案 0 :(得分:0)
这是未经测试的,但我认为它非常接近:
var groupEntries =
from
u in db.Users
where
user.Id == user_id
join
gu in db.GroupUsers
on u.UserId equals gu.UserId
join
g in db.Groups
on gu.GroupId equals g.GroupId
join
ge in db.GroupEntries
on u.GroupdId equals ge.GroupId
into ges
from
ge in ges.DefaultIfEmpty(new GroupEntry { EntryId = 0, GroupId = g.GroupId })
select
ge;
我认为您不需要使用into
,除非您计划进行进一步处理,例如DefaultIfEmpty()
。请注意,DefaultIfEmpty()
的第二次重载允许您输入自定义默认值。因此,您可以创建一个新的GroupEntry
对象,并为每个属性分配所需的值(或将属性保留为空白)。
答案 1 :(得分:0)
//set this to see all queries issued.
myDC.Log = Console.Out;
//setup to load the GroupEntries property of each group
DataLoadOptions o = new DataLoadOptions();
o.LoadWith<Group>(g => g.GroupEntries);
myDC.LoadOptions = o;
//query to get the groups
IQueryable<Group> groupQuery =
from g in myDC.Groups
where g.GroupUsers.Any(gu => gu.User.UserID == user_id)
select g;