我有一个表格的查询(包括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个查询被执行,这不是很好。
编写此查询的正确方法是什么,以便在单个查询中将所有必要的数据提取到数据库?
修改
嗯,如果我在问这个问题之前实际运行了Sql跟踪,它可能会有所帮助。我假设,因为内部属性类型为IQueryable
,它会延迟加载...但经过一些实际测试后,事实证明Linq to Entities足够智能立即运行整个查询。
抱歉浪费你所有的时间。我会删除这个问题,但由于它已经有答案,我不能。也许它可以作为某种警告,让其他人在假设它是真的之前测试你的假设!
答案 0 :(得分:1)
在呼叫大陆时,请将国家/地区包含在您的模型中。有这样的事情:
var continents = db.Continent.Include(c => c.Countries).ToArray();
然后你可以在没有iQueryable对象的情况下进行linq操作。
答案 1 :(得分:0)
我认为这应该有用(将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
})
});