[英]How to avoid “select n+1” pattern in Linq
我有以下形式的查詢(包括LinqKit):
Expression<Func<Country, DateTime, bool>> countryIndepBeforeExpr =
(ct, dt) => ct.IndependenceDate <= dt;
DateTime someDate = GetSomeDate();
var q = db.Continent.AsExpandable().Select(c =>
new
{
c.ID,
c.Name,
c.Area,
Countries = c.Countries.AsQueryable()
.Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
.Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
});
現在我想通過迭代q
...但由於Countries
的每個元素的屬性的類型的IQueryable
,這將是懶加載,導致被執行N + 1個查詢,這是不是很好。
編寫此查詢以便所有必要的數據將在單個查詢中提取到db的正確方法是什么?
編輯
嗯,如果我在問這個問題之前實際運行了Sql跟蹤,那可能會有所幫助。 我以為 ,因為內財產是類型的IQueryable
,這將是懶加載...但是做了一些實際測試后,事實證明,LINQ到實體是足夠聰明的同時運行整個查詢。
很抱歉浪費您的全部時間。 我將刪除該問題,但是由於它已經有了答案,所以不能。 也許可以作為對他人的某種警告,在假設它成立之前對您的假設進行檢驗 !
呼叫大洲時,將國家/地區包括在模型中。 用這樣的東西:
var continents = db.Continent.Include(c => c.Countries).ToArray();
然后,您可以在沒有iQueryable對象的情況下進行linq操作。
我認為這應該工作(將AsExpandable()
移到IQueryable
根目錄):
var q = db.Continent
.AsExpandable()
.Select(c => new
{
c.ID,
c.Name,
c.Area,
Countries = c.Countries
.Where(ct => countryIndepBeforeExpr.Invoke(ct, someDate))
.Select(ct => new {ct.ID, ct.Name, ct.IndependenceDate})
});
如果沒有,請創建兩個IQueryable
並將它們連接在一起:
var continents = db.Continents;
var countries = db.Countries
.AsExpandable()
.Where(c => countryIndepBeforeExpr.Invoke(c, someDate))
.Select(c => new { c.ID, c.Name, c.IndependenceDate });
var q = continents.GroupJoin(countries,
continent => continent.ID,
country => country.ContinentId,
(continent, countries) => new
{
continent.ID,
continent.Name,
continent.Area,
Countries = countries.Select(c => new
{
c.ID,
c.Name,
c.IndependenceDate
})
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.