【问题标题】:LINQ Method that returns set based on filtered sub-set基于过滤子集返回集合的 LINQ 方法
【发布时间】:2026-02-22 10:00:02
【问题描述】:

我有 2 张桌子。 1 个实体,每行 1 个。另一个只是我的 EntitiesID 和 EmployeeID 的映射表。我正在尝试编写一个 LINQ 方法,该方法从第一个表中返回所有实体,其中 EntityID 在由 EmployeeID 过滤的映射表中。

简化表结构示例 TaskTable: ID, Description, Status TaskViewTable: ID, TaskID, EmployeeID

所以我想根据 EmployeeID 从 TaskTable 返回 ID 位于 TaskViewTable 的子查询结果中的所有行。

对在 LINQ 中执行此操作有任何帮助吗?我在两张桌子之间也设置了一对多。我知道有类似的问题,也许我很密集,但它们似乎并不完全适用于我所问的问题。(例如Linq Return Filtered Children

很抱歉忘记展示我目前所拥有的:

IQueryable<tblTask> tTask=context.GetTable<tblTask>();
return tTask.Where(t => t.tblTasksViews.Where(v => v.EmployeeID == empID))

但是,它不喜欢我的 whereunkown method Where(?)

【问题讨论】:

    标签: c# .net linq linq-to-sql


    【解决方案1】:

    这样的事情应该可以解决问题:

    var tasks = tTask.Where(t => 
        tTaskView.Where(v => v.ID == empId).Select(v => v.TaskId).Contains(t.ID));
    

    您可以将以上内容分为两部分:

    //1.) Get all task views for the employeeID and only select the mapped TaskId
    var taskViews = tTaskView.Where(v => v.ID == empId).Select(v => v.TaskId); //taskViews = IEnumerable<int>
    
    //2.) Then get all tasks from the filtered task ids  
    var tasks = tTask.Where(t => taskViews.Contains(t.ID));
    

    更新

    //3.) Project filtered results into IEnumerable<Task>
    return tasks.Select(t => new Task() 
    { 
        ID = t.ID, 
        ActionableID = t.ActionableID, 
        StatusID = t.StatusID, 
        TypeID = t.TypeID, 
        Description = t.Description 
    });
    

    当然,您可以将所有内容串成一个漂亮的单线:

    public List<Task> GetTasks(int empId) 
    {
        return tTask
            .Where(t => tTaskView.Where(v => v.ID == empId).Select(v => v.TaskId).Contains(t.ID))
            .Select(t => new Task() 
            { 
                ID = t.ID, 
                ActionableID = t.ActionableID, 
                StatusID = t.StatusID, 
                TypeID = t.TypeID, 
                Description = t.Description 
            }).ToList();
    }
    

    【讨论】:

    • 在教育之外打破它是否有价值?非常感谢您的回答。
    • 不,据我所知没有功能价值。分解它通常更容易阅读和理解。不过,我更喜欢单线。
    • 好的,最后澄清一下。如何指定要选择的字段?即我有一个要创建并填充的任务对象。通常我会做这样的事情.Select(t =&gt; new Task() { ID=t.ID, ActionableID=t.ActionableID, StatusID=t.StatusID, TypeID=t.TypeID, Description=t.Description, })
    • 你仍然可以这样做。只需将那一点拍到最后一条语句的末尾即可。请参阅我编辑的答案。
    【解决方案2】:

    试试这样的:

    var query =
        from tt in TaskTable
        join tvt in TaskViewTable on tt.ID equals tvt.TaskID into xs
        where xs.Any(z => z.EmployeeID == empID)
        select tt;
    

    【讨论】:

    • EmpID 是如何影响这一点的。已经很晚了,我可能很密集,但我不需要 tvt.EmpID == EmpID 的 TaskViewTable 上的位置(在参数中传递?
    • 例如,也许这个where xs.Any(z =&gt; z.EmployeeID == empID) 会完成我想要的?
    • 从你对桌子的描述来看,EmployeeID 并不适合你的桌子。但是,您对我的.Any() 电话的更改是正确的。我将编辑我的答案。