我一直在研究一些LINQ,我似乎无法弄清楚如何过滤这些数据。我仍然是LINQ的新手,这是我遇到的第一个真正的绊脚石。
我有桌子:
TaskID |名称| TypeID | ParentTaskID
值:
1 | TaskName | 1 | NULL
2 | TASKNAME | 6 | NULL
3 | TASKNAME | 6 | 4
4 | TASKNAME | 2 | NULL
5 | TASKNAME | 6 | 4
6 | TASKNAME | 3 | 4
7 | TASKNAME | 6 | 1
8 | TASKNAME | 6 | 1
9 | TASKNAME | 2 | NULL
SubTask是具有ParentTaskID的任务。
我需要使用此条件获取所有任务:
因此我希望能够回来
3 | TASKNAME | 6 | 4
4 | TASKNAME | 2 | NULL
5 | TASKNAME | 6 | 4
6 | TASKNAME | 3 | 4
9 | TASKNAME | 3 | NULL
上表中的结果如下:
删除了TaskID 1,因为TaskID 7& 8是SubTasks,TypeID = 6
删除了TaskID 2,因为它没有SubTasks且TypeID = 6
TaskID 7& 8被删除,因为它们是ParentTask,TypeT = 6,用于ParentTask 1
甚至可以在LINQ中执行此操作,还是必须驻留在foreach循环中执行此操作?
所以我最终以Foreach的老式方式做了这件事,让Resharper将它可以转换回LINQ。
var parents = tasks.Where(task => task.SubTasks.Any());
var tasksWithNoSubs = tasks.Where(task => !task.SubTasks.Any());
var parentIdsToRemove = new List<int?>();
var childIdsToRemove = new List<int?>();
foreach (var parent in parents)
{
var children = tasks.Where(task => task.ParentTaskID == parent.Id);
if (children.All(task => task.StatusId == 6))
{
parentIdsToRemove.Add(parent.Id); //mark this parent for removal
childIdsToRemove.AddRange(Enumerable.Select(children.Select(child => child.Id), dummy => (int?) dummy));
}
}
//get all Tasks that have NO Subtasks and also have a StatusID = 6
parentIdsToRemove.AddRange(Enumerable.Select((from task in tasksWithNoSubs where task.StatusId == 6 select task.Id), dummy => (int?) dummy));
//get a list of children with an Id contained in the list parentIdsToRemove
var tasksToRemove =
tasks.Where(task => parentIdsToRemove.Contains(task.Id) || childIdsToRemove.Contains(task.Id));
//remove the tasks from the collection
tasks = tasks.Where(task => !tasksToRemove.Contains(task));
答案 0 :(得分:-1)
您应该直接在您的任务对象上生成属性(由实体框架生成,其中包括对父/子的引用,我假设父文件名为ParentTask,子项在我的示例中命名为Tasks,相应地重命名。 #39; t想要使用ID这是非常不同的EF,EF&amp; linq的全部意义在于让它处理所有数据库非规范化无意义并使用对象图。
YourContext.Tasks
// Only keep those where it isn't true that it contains no tasks while being type 6
.Where(t=>!((!t.Tasks.Any()) && t.TypeId == 6))
// Remove all parents that contains subtasks and only have subtasks with type 6
.Where(t=>!(t.Tasks.Any() && t.Tasks.All(sub=>sub.TypeId == 6)))
// Same process on the children, if it has a parent and that parent matches the previous filter
.Where(t=>!(t.ParentTask != null &&(t.ParentTask.Tasks.Any() && t.ParentTask.Tasks.All(sub=>sub.TypeId == 6))))
请注意,这是完全未经测试的,如果它不起作用,请提供指向已编译模型DLL的链接
答案 1 :(得分:-1)
请参阅原始帖子中的解决方案(也在此处发布)。
var parents = tasks.Where(task => task.SubTasks.Any());
var tasksWithNoSubs = tasks.Where(task => !task.SubTasks.Any());
var parentIdsToRemove = new List<int?>();
var childIdsToRemove = new List<int?>();
foreach (var parent in parents)
{
var children = tasks.Where(task => task.ParentTaskID == parent.Id);
if (children.All(task => task.StatusId == 6))
{
parentIdsToRemove.Add(parent.Id); //mark this parent for removal
childIdsToRemove.AddRange(Enumerable.Select(children.Select(child => child.Id), dummy => (int?) dummy));
}
}
//get all Tasks that have NO Subtasks and also have a StatusID = 6
parentIdsToRemove.AddRange(Enumerable.Select((from task in tasksWithNoSubs where task.StatusId == 6 select task.Id), dummy => (int?) dummy));
//get a list of children with an Id contained in the list parentIdsToRemove
var tasksToRemove =
tasks.Where(task => parentIdsToRemove.Contains(task.Id) || childIdsToRemove.Contains(task.Id));
//remove the tasks from the collection
tasks = tasks.Where(task => !tasksToRemove.Contains(task));
感谢大家的贡献,def学到了很多关于LINQ的知识。
答案 2 :(得分:-3)
第二次非常大的编辑
右键!所以,经过很长一段时间和一些误解后第三次幸运 - 这里有一个声明:
entities.
// discard tasks of type 6 and with no subtasks
Where(x => !(x.TypeId == 6 && x.ParentTaskId == null &&
!entities.Any(y => y.ParentTaskId == x.TaskId))).
// discard tasks with subtasks where all those subtasks are of type 6
Where(x => !(entities.Any(y => y.ParentTaskId == x.TaskId) &&
entities.Count(y => y.ParentTaskId == x.TaskId) ==
entities.Count(y => y.ParentTaskId == x.TaskId && y.TypeId == 6))).
// discard subtasks that have parents that are not to be found in the list of
// tasks that were not discarded for having subtasks that were all of type 6.
Where(z => z.ParentTaskId == null ||
entities.Where(x => !(entities.Any(y => y.ParentTaskId == x.TaskId) &&
entities.Count(y => y.ParentTaskId == x.TaskId) ==
entities.Count(y => y.ParentTaskId == x.TaskId && y.TypeId == 6))).
Any(y => y.TaskId == z.ParentTaskId));