第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

如何讓EF高效調(diào)用聚合函數(shù)?

如何讓EF高效調(diào)用聚合函數(shù)?

C#
猛跑小豬 2021-11-07 20:39:07
我正在嘗試編寫一個(gè) LINQ-to-entities 查詢,它將獲取ICollection我的主要對(duì)象的導(dǎo)航屬性,并將一些元數(shù)據(jù)附加到每個(gè)對(duì)象,這是通過將每個(gè)對(duì)象連接到另一個(gè)數(shù)據(jù)庫表并使用聚合函數(shù)來確定的。所以主要對(duì)象是這樣的:public class Plan{    ...    public virtual ICollection<Room> Rooms { get; set; }}我的查詢是這樣的:var roomData = (    from rm in plan.Rooms    join conf in context.Conferences on rm.Id equals conf.RoomId into cjConf    select new {        RoomId = rm.Id,        LastUsedDate = cjConf.Count() == 0 ? (DateTime?)null : cjConf.Max(conf => conf.EndTime)    }).ToList();我想要的是生成一些高效的 SQL,使用聚合函數(shù)MAX來計(jì)算LastUsedDate,如下所示:SELECT    rm.Id, MAX(conf.EndTime) AS LastUsedDateFROM    Room rmLEFT OUTER JOIN    Conference conf ON rm.Id = conf.RoomIdWHERE    rm.Id IN ('a967c9ce-5608-40d0-a586-e3297135d847', '2dd6a82d-3e76-4441-9a40-133663343d2b', 'bb302bdb-6db6-4470-a24c-f1546d3e6191')GROUP BY    rm.id但是當(dāng)我分析 SQL Server 時(shí),它顯示了來自 EF 的這個(gè)查詢:SELECT     [Extent1].[Id] AS [Id],     [Extent1].[RoomId] AS [RoomId],     [Extent1].[ProviderId] AS [ProviderId],     [Extent1].[StartTime] AS [StartTime],     [Extent1].[EndTime] AS [EndTime],     [Extent1].[Duration] AS [Duration],     [Extent1].[ParticipantCount] AS [ParticipantCount],     [Extent1].[Name] AS [Name],     [Extent1].[ServiceType] AS [ServiceType],     [Extent1].[Tag] AS [Tag],     [Extent1].[InstantMessageCount] AS [InstantMessageCount]    FROM [dbo].[Conference] AS [Extent1]所以它從內(nèi)存中選擇所有內(nèi)容Conference并Max()在內(nèi)存中進(jìn)行計(jì)算,這是非常低效的。如何讓 EF 使用聚合函數(shù)生成正確的 SQL 查詢?
查看完整描述

2 回答

?
慕田峪9158850

TA貢獻(xiàn)1794條經(jīng)驗(yàn) 獲得超7個(gè)贊

等效的 LINQ to Entities 查詢,它密切轉(zhuǎn)換為您所追求的 SQL 查詢,如下所示:


var roomIds = plan.Rooms.Select(rm => rm.Id);


var query =

    from rm in context.Rooms

    join conf in context.Conferences on rm.Id equals conf.RoomId

    into rmConf from rm in rmConf.DefaultIfEmpty() // left join

    where roomIds.Contains(rm.Id)

    group conf by rm.Id into g

    select new

    {

        RoomId = g.Key,

        LastUsedDate = g.Max(conf => (DateTime?)conf.EndTime)

    };

訣竅是從 EF 開始查詢IQueryable,從而允許它完全轉(zhuǎn)換為 SQL,而不是從plan.Rooms有問題的查詢中開始,這IEnumerable使得整個(gè)查詢?cè)趦?nèi)存中執(zhí)行(context.Conferences被視為IEnumerable并導(dǎo)致將整個(gè)表加載到記憶)。


SQLIN子句是通過in memoryIEnumerable<Guid>和Containsmethod實(shí)現(xiàn)的。


最后,無需檢查計(jì)數(shù)。SQL 自然會(huì)處理nulls,您只需要確保調(diào)用可為空的Max重載,這是通過強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)的(DateTime?)conf.EndTime。不需要像在 LINQ to Objects 中那樣檢查conf,null因?yàn)?LINQ to Entities/SQL 自然也會(huì)處理(只要接收器變量可以為空)。


查看完整回答
反對(duì) 回復(fù) 2021-11-07
?
揚(yáng)帆大魚

TA貢獻(xiàn)1799條經(jīng)驗(yàn) 獲得超9個(gè)贊

由于plan.Rooms沒有IQueryable附加查詢提供程序,連接語句被編譯為Enumarable.Join. 這意味著在其他運(yùn)算符應(yīng)用于它之前,它c(diǎn)ontext.Conferences被隱式轉(zhuǎn)換為IEumerable并且其內(nèi)容被拉入內(nèi)存。


您可以通過不使用來解決此問題join:


var roomIds = plan.Rooms.Select(r => r.Id).ToList();

var maxPerRoom = context.Conferences

    .Where(conf => roomIds.Contains(conf.RoomId))

    .GroupBy(conf => conf.RoomId)

    .Select(g => new

    {

        RoomId = g.Key,

        LastUsedDate = g.Select(conf => conf.EndTime)

            .DefaultIfEmpty()

            .Max()

    }

).ToList();


var roomData = (

    from rm in plan.Rooms

    join mx in maxPerRoom on rm.Id equals mx.RoomId

    select new 

    {

        RoomId = rm.Id,

        LastUsedDate = mx.LastUsedDate

    }

).ToList();

第一步LastUsedDate從上下文收集數(shù)據(jù),然后與plan.Rooms內(nèi)存中的集合連接。如果您對(duì)返回/顯示房間 ID 以外的任何其他內(nèi)容不感興趣,則甚至不需要最后一步,但這取決于您。


查看完整回答
反對(duì) 回復(fù) 2021-11-07
  • 2 回答
  • 0 關(guān)注
  • 336 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)