【问题标题】:Linq, linq where in where in wherelinq, linq 哪里哪里哪里哪里
【发布时间】:2018-06-23 13:39:57
【问题描述】:

我有一个这样的 SQL 语句:

SELECT 
    projects.name, projects.id, 
    issues.subject, issues.description, 
    time_entries.spent_on, time_entries.hours 
FROM 
    (time_entries 
INNER JOIN 
    projects ON time_entries.project_id = projects.id) 
INNER JOIN 
    issues ON time_entries.issue_id = issues.id
WHERE 
    (((projects.id) IN (26, 27)) 
    AND ((issues.subject) NOT LIKE "*zlecane*")) 
    AND MONTH(spent_on) = MONTH(CURRENT_TIMESTAMP) 
GROUP BY 
    name, id, subject, spent_on

我需要用 Linq 来写。

我是这样写的,但它不起作用——它返回一个空列表:

ProjectIdsForBudgets - 包含 26 和 27 的列表

Projects.Include(x => x.Issues)
        .ThenInclude(k => k.TimeEntries)
        .Where(x => ProjectIdsForBudgets.Contains(x.Id) && 
                    x.Issues.Any(y => !y.Subject.Contains("zlecane") &&
                    y.TimeEntries.Any(K => K.SpentOn >= firstDayOfTheMonth)
              )
         )

分组我们可以跳过

你能帮帮我吗?

【问题讨论】:

  • 调试时哪个条件不适合你?只需一一添加并测试。
  • 哪种 LINQ 风格(实体框架?)和哪个数据库品牌?请使用适当的标签(+ 版本)。
  • 以小块测试您的代码。首先省略 where 并确保你得到结果。然后一次添加一个 where 以确保您获得正确的结果,直到您找出导致问题的查询部分。
  • firstDayOfTheMonth 是如何定义的?

标签: c# .net linq entity-framework-core


【解决方案1】:

所以你有一个Projects 序列和一个Issues 序列。此外,您还有一系列TimeEntries,其中每个TimeEntry 使用外键TimeEntry.ProjectId 恰好属于一个Project。每个TimeEntry 也恰好属于一个Issue,使用外键TimeEntry.IssueId

您希望将这三个表的主键和外键连接起来。您只想保留连接结果的某些元素(位置)。其余元素应分组为具有相同nameidsubjectspentOn 的组。最后,您想从每个组及其元素中选择一些属性。

如果你有类似实体框架的东西,你的项目将有一个 TimeEntries 的虚拟集合,每个 TimeEntry 都有一个对项目的虚拟引用。如果使用该方法,实体框架将理解需要连接。您可以使用表之间的引用。

这将在稍后讨论。首先使用连接三表的方法

方法:连接三张表

通常我会使用方法语法。但是method syntax looks hideous if you join three tables. 这些是我唯一使用查询语法的时候。

我以较小的步骤进行此操作。随意把它变成一个大 linq

var joinedItems = from timeEntry in timeEntries
    join project in project on timeEntry.ProjectId equals project.Id
    join issue in issues on timeEntry.IssueId equals issue.Id
    select new
    {
        TimeEntry = timeEntry,
        Project = Project,
        Issue = Issue,
    };

只保留部分连接项:

int currentMonth = DateTime.Now.Month;
var subsetJoinedItems = joinedItems.Where(joinedItem =>
   (joinedItem.Project.Id == 26 || joinedItem.Project.Id == 27)
   && joinedItem.Issue.Subject.Contains("zlecane")   // consider ignore case
   && joinedItem.TimeEntry.SpentOn.Month == currentMonth);

将生成的元素分组为相同的 [name、id、subject、spend_on] 组:

var groups = subsetJoinedItems.GroupBy(joinedItem => new
{
     ProjectId = joinedItem.Project.Id,
     ProjectName = joinedItem.Project.Name,
     Subject = joinedItem.Issue.Subject,
     Spent_on = joinedItem.TimeEntry.SpentOn,
});

最后,从每个组中选择您要保留的项目:

var result = groups.Select(group => new
{
    ProjectId = group.Key.ProjectId,
    ProjectName = group.Key.ProjectName,
    Subject = group.Key.Subject,
    SpentOn = group.Key.SpentOn,

    // remaining properties: SQL query seems incorrect
    ...
});

在实体框架中使用类关系

如果您有类似于实体框架的东西,那么您的一对多关系将使用集合来实现:

class TimeEntry
{
     public int Id {get; set;}

     // every TimeEntry belongs to exactly one Project using foreign key
     public int ProjectId {get; set;}
     public virtual Project Project {get; set;}

     // every TimeEntry belongs to exactly one Issue using foreign key
     public int IssueId {get; set;}
     public virtual Issue Issue {get; set;}
}

如果你有这样的东西,你不必自己做连接,实体框架会理解它:

var result = TimeEntries.Where(timeEntry =>
    (timeEntry.ProjectId == 26 || timeEntry.ProjectId == 27)
       && timeEntry.Issue.Subject.Contains("zlecane")   // consider ignore case
       && TimeEntry.SpentOn.Month == currentMonth)
    .GroupBy(timeEntry => new
    {
        ProjectId = joinedItem.Project.Id,
        ProjectName = joinedItem.Project.Name,
        Subject = joinedItem.Issue.Subject,
        Spent_on = joinedItem.TimeEntry.SpentOn,
    })
    .Select(group => new
    {
        ProjectId = group.Key.ProjectId,
        ProjectName = group.Key.ProjectName,
        Subject = group.Key.Subject,
        SpentOn = group.Key.SpentOn,
        ...
     });

【讨论】:

    猜你喜欢
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多