簡體   English   中英

.Net核心實體框架Linq Fluent API查詢無法創建/執行在數據庫上運行的正確SQL查詢

[英].Net Core Entity Framework Linq Fluent API query doesn't create/execute correct SQL query ran on database

我寫了這個SQL查詢:

SELECT R.Name, R.PointsNeeded, A.EmailAddress, SUM(PH.Points) AS TotalPoints
FROM Business AS B
INNER JOIN Reward AS R ON R.BusinessId = B.Id
INNER JOIN Account AS A ON A.BusinessId = B.Id
INNER JOIN PointHistory PH ON PH.AccountId = A.Id
WHERE B.Serial = 'F5C17337-F675-4270-8A57-FE2F5782B5CB'
GROUP BY R.Name, A.EmailAddress, R.PointsNeeded
HAVING SUM(PH.Points) >= R.PointsNeeded
ORDER BY A.EmailAddress ASC

返回3個結果。 我想使用linq / fluent api創建它。 我無法弄清楚如何做HAVING所以我創造了這個:

var eligableAccounts = _context.Business
           .Join(_context.Reward, B => B.Id, R => R.BusinessId, (Business, Rewards) => new { Business, Rewards })
           .Join(_context.Account, BusinessRewards => BusinessRewards.Business.Id, A => A.BusinessId, (BusinessRewards, Account) => new
           {
               Business = BusinessRewards.Business,
               Rewards = BusinessRewards.Rewards,
               Account = Account
           })
            .Join(_context.PointHistory, Model => Model.Account.Id, PointHistory => PointHistory.AccountId, (Model, PointHistory) => new
            {
                Business = Model.Business,
                Rewards = Model.Rewards,
                Account = Model.Account,
                PointHistory = PointHistory
            })
            .Where(Model => Model.Business.Serial == businessSerial)
            .GroupBy(Model => new { Model.Rewards.Name, Model.Account.EmailAddress, Model.Rewards.PointsNeeded })
            .Where(Group => Group.Sum(Model => Model.PointHistory.Points) >= Group.Key.PointsNeeded)
            .Select(Group => new {
                TotalPoints = Group.Sum(Model => Model.PointHistory.Points),
                EmailAddress = Group.Key.EmailAddress,
                RewardName = Group.Key.Name,
                PointsNeeded = Group.Key.PointsNeeded
            }).ToList();

此方法有效,並且eligableAccounts包含與直接在SQL Management Studio中執行時SQL查詢返回的3個結果相同的結果。 我想看看幕后發生的一切,令我驚訝的是,返回了每個結果集,然后.net做了一些魔術,只得到了我需要的3條記錄。 以下是EF在數據庫上實際執行的操作:

exec sp_executesql N'SELECT [B].[Id], [B].[Code], [B].[LastProcessedDateTime], [B].[Name], [B].[PointRatio], [B].[Serial], [Rewards].[Id], [Rewards].[BusinessId], [Rewards].[Name], [Rewards].[PointsNeeded], [Account].[Id], [Account].[BusinessId], [Account].[City], [Account].[Created], [Account].[EmailAddress], [Account].[EmailSent], [Account].[FirstName], [Account].[LastName], [Account].[Password], [Account].[PasswordSalt], [Account].[Phone], [Account].[RoleId], [Account].[State], [Account].[Updated], [Account].[VerificationCode], [Account].[Verified], [Account].[ZipCode], [PointHistory].[Id], [PointHistory].[AccountId], [PointHistory].[Points], [PointHistory].[TransactionDate], [PointHistory].[TransactionType]
FROM [Business] AS [B]
INNER JOIN [Reward] AS [Rewards] ON [B].[Id] = [Rewards].[BusinessId]
INNER JOIN [Account] AS [Account] ON [B].[Id] = [Account].[BusinessId]
INNER JOIN [PointHistory] AS [PointHistory] ON [Account].[Id] = [PointHistory].[AccountId]
WHERE [B].[Serial] = @__businessSerial_0
ORDER BY [Rewards].[Name], [Account].[EmailAddress], [Rewards].[PointsNeeded]',N'@__businessSerial_0 nvarchar(4000)',@__businessSerial_0=N'F5C17337-F675-4270-8A57-FE2F5782B5CB'

直接在數據庫上執行時,此SQL返回所有結果,因為EF未創建HAVING語句。 有誰知道我該如何編寫我的EF代碼來生成正確的查詢並執行? 這很可能會開始返回數十萬條記錄,我不喜歡.net的想法來處理內存中結果集的減少。 我寧願將其推送到數據庫。 如果我必須創建一個存儲過程,則可以這樣做,但實際上並不想這樣做。 任何幫助表示贊賞。 謝謝!

盡管我無法解決EF Core的局限性(除非您想切換到完整EF),但是可以將SQL轉換為LINQ。 我發現更容易使用查詢語法進行如下分組:

var ans = from b in _context.Business
          join r in _context.Reward on b.Id equals r.BusinessId
          join a in _context.Account on b.Id equals a.BusinessId
          join ph in _context.PointHistory on a.Id equals ph.AccountId
          where b.Serial == "F5C17337-F675-4270-8A57-FE2F5782B5CB"
          group new { b, r, a, ph } by new { r.Name, a.EmailAddress, r.PointsNeeded } into grp
          let TotalPoints = grp.Sum(g => g.ph.Points)
          where TotalPoints >= grp.Key.PointsNeeded
          orderby grp.Key.EmailAddress
          select new { grp.Key.Name, grp.Key.PointsNeeded, grp.Key.EmailAddress, TotalPoints };

請注意,翻譯是直截了當的,幾乎是機械的。

您使用lambda語法進行的翻譯對我來說直截了當。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM