我有实体Group
和User
Group
实体具有Users
属性,该属性是用户列表
用户有一个名为IsEnabled
的属性。
我想编写一个linq查询,该查询返回Group
的列表,该列表仅包含User
为真的IsEnabled
。
所以例如,对于下面的数据
AllGroups
A组
用户1(IsEnabled = true)
用户2(IsEnabled = true)
用户3(IsEnabled = false)
B组
用户4(IsEnabled = true)
用户5(IsEnabled = false)
用户6(IsEnabled = false)
我想得到
FilteredGroups
A组
用户1(IsEnabled = true)
用户2(IsEnabled = true)
B组
用户4(IsEnabled = true)
我尝试了以下查询,但Visual Studio告诉我
[不能将属性或索引器'用户'分配给 - 它是只读的]
FilteredGroups = AllGroups.Select(g => new Group()
{
ID = g.ID,
Name = g.Name,
...
Users = g.Users.Where(u => u.IsInactive == false)
});
谢谢你的帮助!
答案 0 :(得分:13)
没有“好”的方法可以做到这一点,但是你可以试试这个 - 将Group
和过滤的Users
投射到一个匿名对象上,然后Select
只调整Groups
{1}}:
var resultObjectList = AllGroups.
Select(g => new
{
GroupItem = g,
UserItems = g.Users.Where(u => !u.IsInactive)
}).ToList();
FilteredGroups = resultObjectList.Select(i => i.GroupItem).ToList();
这不是一个记录的功能,与EF构造SQL查询的方式有关 - 在这种情况下,它应该过滤掉子集合,因此您的FilteredGroups
列表将只包含活动用户。
如果这样可行,您可以尝试合并代码:
FilteredGroups = AllGroups.
Select(g => new
{
GroupItem = g,
UserItems = g.Users.Where(u => !u.IsInactive)
}).
Select(r => r.GroupItem).
ToList();
(这是未经测试的,结果取决于EF将如何处理第二个Select
,所以如果你在尝试之后让我们知道哪种方法有效,那就太好了。
答案 1 :(得分:9)
我设法通过颠倒查询来完成此操作:
var users = (from user in Users.Include("Group")
where user.IsEnabled
select user).ToList().AsQueryable()
from (user in users
select user.Group).Distinct()
通过使用ToList(),您可以强制执行到数据库的往返,因为否则延迟执行会妨碍。第二个查询仅重新排序检索到的数据。
注意:之后您可能无法更新您的实体!
答案 2 :(得分:1)
尝试这样的事情,你仍然会拥有你的实体:
FilteredGroups = AllGroups.Select(g => new
{
Group = g,
Users = g.Users.Where(u => u.IsInactive == false)
}).AsEnumerable().Select(i => i.Group);
这样你仍然可以使用Group.Users
答案 3 :(得分:0)
如果您想保留实体结构,请尝试以下方法:
var userGroups = context.Users.Where(u => !u.IsInactive).GroupBy(u => u.Group);
foreach (var userGroup in userGroups)
{
// Do group stuff, e.g.:
foreach (var user in userGroup)
{
}
}
你当然可以修改你的实体!
答案 4 :(得分:0)
使用内部linq查询
var FilteredGroups = (from g in AllGroups
select new Group()
{
ID = g.ID,
Name = g.Name,
...
Users = (from user in g.Users
where user.IsInactive == false
select user).ToList()
});