我应该在linq-to-sql查询中使用什么集合?可查询vs可枚举与列表

时间:2015-11-25 14:08:24

标签: c# linq linq-to-sql linq-to-entities

想象一下以下几个类:

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

class Underage
{
    public int Age { get; set; }
}

我这样做:

var underAge = db.Underage.Select(u => u.Age)   .ToList()/AsEnumerable()/AsQueryable() 

var result = db.Persons.Where(p => underAge.Contains(p.Age)).ToList();

什么是最佳选择?如果我致电ToList(),项目将被检索一次,但如果我选择AsEnumerableAsQueryable,则每次从Where()的数据库中选择一个人时,都会执行这些项目({1}}如果它是如何工作的,我不太了解数据库在后台做了什么?)

当Underage包含数千条记录与少量记录时,还有更大的差异吗?

3 个答案:

答案 0 :(得分:2)

无。

你绝对不希望ToList()在这里,因为这会将所有匹配的值加载到内存中,然后用它来编写result的查询,这个查询具有大量IN (…)其中的1}}子句。当你真正想要的是首先从数据库中获取匹配值时,这是一种浪费,其查询类似于

SELECT *
FROM Persons
WHERE EXISTS(
  SELECT NULL FROM 
  FROM Underage
  WHERE Underage.age = Persons.age
)

AsEnumerable()经常阻止在数据库上完成任务,但提供者可能会检查源并撤消AsEnumerable()的影响。 AsQueryable()很好,但在这种情况下实际上并没有做任何事情。

你不需要其中任何一个:

var underAge = db.Underage.Select(u => u.Age);

var result = db.Persons.Where(p => underAge.Contains(p.Age)).ToList();

(就此而言,检查你真的需要在最后一行ToList();如果你要对它进行进一步的询问,它可能会伤害他们,如果你&# 39;如果您要存储它们或者做很多内存操作而无法在Linq中完成,那么只需要列举结果就会浪费时间和记忆。 #39;将会变得更好。)

答案 1 :(得分:2)

如果您将第一个查询保留为

  var underage = db.Underage.Select(u => u.Age);

它将是IQueryable类型,它不会ping你的数据库(acutaly称为延迟执行)。一旦你真的想要执行对数据库的调用,你可以使用贪婪的运算符,如 .ToList(),. ToArray(),. ToDictionary()。这将为您的结果变量提供一个IEnumerable集合。

See linq deferred execution

答案 2 :(得分:1)

您应该使用join来获取数据。

var query = (from p in db.Persons
             join u in db.Underage
              on u.Age equals p.Age
             select p).ToList();

如果您在上面的查询中没有使用.ToList(),则会返回Person类型的IEnumerable,并且在您使用该对象时将获取实际数据。

根据您要使用的场景,所有内容同样优秀的ToList(),AsEnurmeable和Querable。对于你的情况ToList看起来对我很好,因为你只想获取有未成年人的人员名单