我正在学习Linq查询,例如,每当我执行FirstOrDefault()
或ToList()
时,有人告诉我,将向数据库发出请求。因此,我试图在Person DbSet中使用多个包含项来执行Linq,如下所示:
DbSet.Include(x => x.ManyToManyProperty)
.ThenInclude(x => x.Company)
.FirstOrDefault();
但是我想要的只是活跃的公司,但是要在FirstOrDefault()
之前这样做(因此,我不会从数据库中带来不需要的东西)我做了Select
,所以代码如下:
DbSet.Include(x => x.ManyToManyProperty)
.ThenInclude(x => x.Company)
.Select(x => new Person
{
ManyToManyProperty = x.ManyToManyProperty
.Where(c => c.Company.Active)
.Select(c => new ManyToManyProperty
{
Company = c.Company
}).ToList()
}
.FirstOrDefault();
所以上面的代码是问题所在,我在ToList()
属性上执行ManyToMany
,然后在FirstOrDefault()
DbSet上执行Person
,这将使Linq正常运行两次访问数据库,影响性能,而且我找不到只用FirstOrDefault()
来获取我想要的所有信息的方法。
任何人都可以给我一个想法,怎么做吗?另外,如果对代码改进有任何建议,将不胜感激。
答案 0 :(得分:-1)
使用Include通常不是一个好主意,主要是因为缺点多于优点。 您可能最终会从数据库中提取超出所需的数据,并且Include的性能取决于所包含的所有表中的行数(性能将与所有表的行数的乘积成正比)。
使用连接是一个更好的主意,这样您就可以准确地得到所需的内容。另请阅读有关延迟加载与快速加载的信息。那应该给你带来更好的画面。
如果要使用来自另一个查询的数据,请不要给它一个.ToList()
。如果仅使用查询,则该查询采用IQueryable形式,并且可用作表本身(将其用于联接,分组依据,任何您想要的东西。它基本上转换为SELECT查询,可以在其他地方使用)。
此查询会有所帮助
var result =
from ds in DbSet
join mtmp in ManyToManyProperty on ds.Property1 equals mtmp.Property1
join cmp in Company on mtmp.Property2 equals cmp.Property2
join p in Person on cmp.Property3 equals p.Property3
where p.IsActive //taking company as Active if it has active Persons
select cmp;
此查询将为您提供所有拥有活跃人员的公司。这可能是一家公司也可能不是一家公司,因此FirstOrDefault在这里不适用,因为该查询可能具有0到N个条目,而FirstOrDefault则适用于0到1个条目。
Ps。这只会打一次数据库。
编辑1: 阅读注释并查看代码后,这是一个最可能起作用的查询:
var result = (from mtmp in db.ManyToManyProperty
join cmp in db.Company on mtmp.Company equals cmp.Id
join p in db.Person in cmp.Id equals p.CompanyId
where cmp.IsActive
select p).ToList();
// This needs ToList because there can be many companies which are active.