在延迟加载的集合导航属性中调用.Any()会枚举属性吗?

时间:2015-09-03 19:46:07

标签: c# entity-framework

考虑以下实体:

public class Principal
{
   [Key,DatabaseGenerated]
   public int ID{ get; set; }

   [Key,DatabaseGenerated]
   public virtual ICollection<Dependent> Dependents { get; set; }
}

public class Dependent
{
   [Key]
   public int PrincipalID { get; set; }

   [ForeignKey("PrincipalID")]
   public virtual Principal Principal { get; set; }
}

在以下情形中:

var principal = db.Principals.First();

if( principal.Dependents.Any()){
  // Do stuff
}

对.Any的调用是否会检索依赖实体,或者EF是否足够聪明,可以在商店中执行Exists而不是检索相关记录并对可枚举执行.Any()?

4 个答案:

答案 0 :(得分:1)

实际上没有办法可以发生。

DependentsICollection<T>,而不是IQueryable<T>,因此Any()是标准的LINQ到对象Any()

EF会在你第一次获得财产后立即加载所有对象。

答案 1 :(得分:1)

它将检索所有依赖实体。

该属性为ICollection,表示它实现IEnumerable而不是IQueryable。这意味着Any只是在内存中迭代集合(意味着它需要延迟加载),而不是向查询提供程序发送Expression,让查询提供程序使用{{{}执行任何所需的操作。 1}}。

答案 2 :(得分:1)

由于Dependents导航属性不是IQueryable(并且EF在导航属性上不支持IQueryable),因此一旦加载,整个导航属性数据执行并具体化,并使用Enumerable.Any(Linq-to-Objects)调用进一步的LINQ调用。

答案 3 :(得分:1)

如果您想在数据库上执行 的操作,可以执行以下操作:

if (db.Principals.Take(1).Any(p => p.Dependents.Any()))
{
    // do stuff
}

或者假设您只想使用Principal来对第一个Dependent执行某些操作:

var principal =
    db.Principals.Take(1)
    .Where(p => p.Dependents.Any()))
    .SingleOrDefault();

if (principal != null)
{
    // do stuff with principal...
}