[英]How to include last, filtered, sorted child row in EF6
我想包含一個經過過濾的子行,並且僅包含找到的最后一個。
我可以手動且效率低下地執行此操作,如下所示:
var persons = dbContext.Persons.ToList();
foreach (var person in persons)
{
var lastMatchingNote = person.Notes
.Where(x => x.Type == 5)
.OrderBy(x => x.Date)
.LastOrDefault();
}
但是,此重新查詢每個人。
另外,我可以在原始查詢中將Include()注釋然后過濾到內存中:
var persons = dbContext.Persons.Include("Notes").ToList();
但這會加載所有效率低下的音符。
EF6中執行此操作的最佳方法是什么?
(可以選擇存儲過程,視圖或其他奇異解決方案,但我更喜歡純LINQ-to-Entities解決方案。如果可以防止在涉及Person的所有其他查詢上加載計算字段,那么創建計算字段也可以工作。)
嘗試像這樣查詢數據庫:
var results =
(from p in dbContext.Persons
select new {
person = p,
lastMatchingNote = p.Notes.Where(x => x.Type == 5)
.OrderByDescending(x => x.Date)
.First()
})
.ToList();
或像這樣:
var results =
(from p in dbContext.Persons
let lastMatchingNote = p.Notes.Where(x => x.Type == 5)
.OrderByDescending(x => x.Date)
.First()
select new { person = p, lastMatchingNote })
.ToList();
使用這種方法,您可以調整結果集中的列,從而對實際查詢進行更好的控制。
最后,我決定為這個額外的價值創建一個單獨的視圖。 這看似過高,但是性能非常好,它可以在單個查詢中檢索所有值,考慮到大數據集的性能要求,這是我的方案中的優先級。
所以我有以下觀點:
CREATE VIEW vwperson_lastproactivenote as
SELECT people.person_id AS id,
(SELECT max(notes.note_date) AS max
FROM notes
WHERE notes.person_id = people.person_id AND notes.note_type_id = 5) AS date
FROM people;
然后,我可以建立一個與Person共享主鍵的模型:
public class PersonLastProactiveCall
{
[Required]
[ForeignKey("Id")]
public virtual Person Person { get; set; }
public DateTime? Date { get; set; }
}
...
// On person model
[ForeignKey("Id")]
public virtual PersonLastProactiveCall LastProactiveCall { get; set; }
所以最終我可以這樣稱呼它:
DataContext.Set<Person>().Include("LastProactiveCall").Where(...);
person.LastProactiveCall.Date // <-- Yay!!!!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.