SQL 到 Linq - NET CORE 5

Posted

技术标签:

【中文标题】SQL 到 Linq - NET CORE 5【英文标题】:SQL to Linq - NET CORE 5 【发布时间】:2021-11-05 18:25:35 【问题描述】:

我有一个这样的 SQL 语句:

select      
    b.ActivityRecordId, b.ActivityName, b.ActivityDetail, 
    b.CustomerId, e.CustomerName, 
    b.JobStatusId, c.JobStatusName, b.EstimateStartDate, 
    b.EstimateFinishDate, b.StartedDateTime, b.FinishedDateTime,
    a.ActivityRecordProgressId, a.CustomerContactId, 
    Concat(d.FirstName, ' ', d.MiddleName, ' ', d.LastName) as fullName,
    a.Started, a.Finished, a.ActivityDescription, 
    g.ActivityTypeId, g.ActivityTypeName, a.ActivitySubTypeId, f.ActivitySubTypeName
from        
    ActivityRecordProgress a
right join 
    ActivityRecord b on a.ActivityRecordId = b.ActivityRecordId
left join 
    ActivitySubType f on a.ActivitySubTypeId = f.ActivitySubTypeId
left join 
    ActivityType g on f.ActivityTypeId = g.ActivityTypeId
left join 
    CustomerContact d on a.CustomerContactId = d.CustomerContactId
inner join 
    JobStatus c on b.JobStatusId = c.JobStatusId
inner join 
    Customer e on b.CustomerId = e.CustomerId

然后我尝试将其转换为 Linq:

var obj = (from a in _db.ActivityRecords
           join b in _db.ActivityRecordProgresses on a.ActivityRecordId equals b.ActivityRecordId into ab
           from p in ab.DefaultIfEmpty()
           join c in _db.Customers on a.CustomerId equals c.CustomerId
           join e in _db.CustomerContacts on c.CustomerId equals e.CustomerId
           join d in _db.JobStatuses on a.JobStatusId equals d.JobStatusId
           join f in _db.ActivitySubTypes on p.ActivitySubTypeId equals f.ActivitySubTypeId                      
           join g in _db.ActivityTypes on f.ActivitySubTypeId equals g.ActivityTypeId
           select new OutstandingActivityViewModel  
                          ActivityRecordId = p.ActivityRecordId,
                          ActivityName = a.ActivityName,
                          ActivityDetail = a.ActivityDetail,
                          CustomerId = a.CustomerId,
                          CustomerName = c.CustomerName,
                          JobStatusId = a.JobStatusId,
                          JobStatusName = d.JobStatusName,
                          EstimateStartDate = a.EstimateStartDate,
                          StartedDateTime = a.StartedDateTime,
                          EstimateFinishDateTime = a.EstimateFinishDate,
                          FinishedDateTime = a.FinishedDateTime,
                          FirstName = e.FirstName, MiddleName = e.MiddleName, LastName = e.LastName,
                          Started = p.Started, Finished = p.Finished,
                          ActivityTypeName = g.ActivityTypeName, ActivitySubTypeName = f.ActivitySubTypeName,
                          ActivityDescription = p.ActivityDescription
    ).ToListAsync();

但结果不一样。 SQL 结果是正确的。它只有4条记录。但在 Linq 中,出现了 6 条记录。我确定我的 linq 语法有问题。

谁能告诉我我的语法错误在哪里?

非常感谢 - 谢谢。

【问题讨论】:

你检查EF查询生成的SQL了吗?这可以帮助您调试。 entityframework.net/view-generated-sql 第一个右连接转过来作为左外连接加入,其他左连接变成内连接,不是吗? @VineetDesai,谢谢。 context.database.Log,它在 EF Core 中不起作用。是吗? @ChrᴉzsupportsMonica,linq 语法? 【参考方案1】:

感谢您评论我的问题。这非常有用。 最后,我在使用生成的 SQL 反复试验后找到了答案。以下是 Linq 语法的答案:

var obj = (from a in _db.ActivityRecords
                       join b in _db.ActivityRecordProgresses on a.ActivityRecordId equals b.ActivityRecordId into leftsatu
                       from leftkesatu in leftsatu.DefaultIfEmpty()
                       join c in _db.ActivitySubTypes on leftkesatu.ActivitySubTypeId equals c.ActivitySubTypeId into leftdua
                       from leftkedua in leftdua.DefaultIfEmpty()
                       join d in _db.ActivityTypes on leftkedua.ActivitySubTypeId equals d.ActivityTypeId into lefttiga
                       from leftketiga in lefttiga.DefaultIfEmpty()
                       join e in _db.CustomerContacts on leftkesatu.CustomerContactId equals e.CustomerContactId into leftempat
                       from leftkeempat in leftempat.DefaultIfEmpty()
                       join f in _db.JobStatuses on a.JobStatusId equals f.JobStatusId
                       join g in _db.Customers on a.CustomerId equals g.CustomerId
                       select new OutstandingActivityViewModel
                       
                           ActivityRecordId = a.ActivityRecordId,
                           ActivityName = a.ActivityName,
                           ActivityDetail = a.ActivityDetail,
                           CustomerId = a.CustomerId,
                           CustomerName = g.CustomerName,
                           JobStatusId = a.JobStatusId,
                           JobStatusName = f.JobStatusName,
                           EstimateStartDate = a.EstimateStartDate,
                           StartedDateTime = a.StartedDateTime,
                           EstimateFinishDateTime = a.EstimateFinishDate,
                           FinishedDateTime = a.FinishedDateTime,
                           FirstName = leftkeempat.FirstName,
                           MiddleName = leftkeempat.MiddleName,
                           LastName = leftkeempat.LastName,
                           Started = leftkesatu.Started,
                           Finished = leftkesatu.Finished,
                           ActivityTypeName = leftketiga.ActivityTypeName,
                           ActivitySubTypeName = leftkedua.ActivitySubTypeName,
                           ActivityDescription = leftkesatu.ActivityDescription
                       
                           );

它会生成如下 SQL:

SELECT      [a].[ActivityRecordId], [a].[ActivityName], [a].[ActivityDetail], [a].[CustomerId], [c0].[CustomerName], [a].[JobStatusId], [j].[JobStatusName], 
            [a].[EstimateStartDate], [a].[StartedDateTime], [a].[EstimateFinishDate] AS [EstimateFinishDateTime], [a].[FinishedDateTime], 
            [c].[FirstName], [c].[MiddleName], [c].[LastName], 
            [a0].[Started], [a0].[Finished], [a2].[ActivityTypeName], [a1].[ActivitySubTypeName], [a0].[ActivityDescription]
FROM [ActivityRecord] AS [a]
LEFT JOIN [ActivityRecordProgress] AS [a0] ON [a].[ActivityRecordId] = [a0].[ActivityRecordId]
LEFT JOIN [ActivitySubType] AS [a1] ON [a0].[ActivitySubTypeId] = [a1].[ActivitySubTypeId]
LEFT JOIN [ActivityType] AS [a2] ON [a1].[ActivitySubTypeId] = [a2].[ActivityTypeId]
LEFT JOIN [CustomerContact] AS [c] ON [a0].[CustomerContactId] = [c].[CustomerContactId]
INNER JOIN [JobStatus] AS [j] ON [a].[JobStatusId] = [j].[JobStatusId]
INNER JOIN [Customer] AS [c0] ON [a].[CustomerId] = [c0].[CustomerId]

【讨论】:

以上是关于SQL 到 Linq - NET CORE 5的主要内容,如果未能解决你的问题,请参考以下文章

在 .NET Core 中如何让 Entity Framework Core 在日志中记录由 LINQ 生成的SQL语句

asp.net core 3.0 新手问题:如何这段带“count” 和 group by的sql代码,怎么转成 linq的写法?

Net Core:在洋葱架构中使用OData,将查询参数转换为Linq

.NET Core 3.1 中的 Linq 表达式 GroupBy 错误

EF Core 嵌套 Linq 选择导致 N + 1 个 SQL 查询

Linq 查询在 ASP.NET-Core 3.0 及更高版本中对数字等字符串进行排序