2 回答

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ì)處理(只要接收器變量可以為空)。

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)容不感興趣,則甚至不需要最后一步,但這取決于您。
- 2 回答
- 0 關(guān)注
- 336 瀏覽
添加回答
舉報(bào)