Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将IEnumerable和IQueryable用作对象集类型时的差异_C#_.net_Entity Framework_Ienumerable_Iqueryable - Fatal编程技术网

C# 将IEnumerable和IQueryable用作对象集类型时的差异

C# 将IEnumerable和IQueryable用作对象集类型时的差异,c#,.net,entity-framework,ienumerable,iqueryable,C#,.net,Entity Framework,Ienumerable,Iqueryable,据我所知,当我在IQueryable上使用LINQ扩展方法(使用lambda表达式语法)时,即ObjectSet的实例中,它们被转换为LINQ to SQL查询。我的意思是那个命令 IQueryable<User> users = db.UserSet; var users32YearsOld = users.Where(user => user.Age == 32); 它是否会立即进入数据库(如果是,那么什么时候?在第一行还是第二行)?或者它的行为是否与前面的命令一样,在枚

据我所知,当我在
IQueryable
上使用LINQ扩展方法(使用lambda表达式语法)时,即
ObjectSet
的实例中,它们被转换为LINQ to SQL查询。我的意思是那个命令

IQueryable<User> users = db.UserSet;
var users32YearsOld = users.Where(user => user.Age == 32);
它是否会立即进入数据库(如果是,那么什么时候?在第一行还是第二行)?或者它的行为是否与前面的命令一样,在枚举
users32yearsell
之前不会命中数据库?如果我改用下面的方法,会有什么不同吗

IEnumerable<User> users = db.UserSet;
var users32YearsOld = from user in users where user.Age == 32 select user;
IEnumerable users=db.UserSet;
var users32yearsell=来自用户中的用户,其中user.Age==32选择用户;

谢谢你

关于IQueryable你是对的。至于IEnumerable,它会在分配IEnumerable用户后立即命中数据库


在您提供的示例中,使用Linq扩展与使用语法之间没有真正的区别。有时,其中一个会更方便(见),但在我看来,更多的是个人偏好

这里有一个简单的解释:

IEnumerable<User> usersEnumerable = db.UserSet;
IQueryable<User> usersQueryable = db.UserSet;

var users = /* one of usersEnumerable or usersQueryable */;

var age32StartsWithG = users.Where(user => user.Age == 32)
                            .Where(user => user.Name.StartsWith("G");
IEnumerable用户SEnumerable=db.UserSet;
IQueryable usersQueryable=db.UserSet;
var users=/*usersEnumerable或usersQueryable*/之一;
var age32StartsWithG=users.Where(user=>user.Age==32)
.Where(user=>user.Name.StartsWith(“G”);
如果您使用
usersEnumerable
,当您开始对其进行枚举时,两个
Where
s将按顺序运行;首先
ObjectSet
将获取所有对象,对象将被过滤到32岁的对象,然后这些对象将被过滤到名称以G开头的对象

如果使用
usersQueryable
,两个
Where
s将返回新的对象,这些对象将累积选择条件,当您开始枚举时,它将把所有条件转换为查询。这会产生明显的差异

通常,您不必担心,因为在声明变量时,您会说
var-users
ObjectSet-users
,这意味着C#会知道您对调用
ObjectSet
上可用的最具体的方法以及
IQueryable
查询运算符方法感兴趣(
Where
Select
,…)比
IEnumerable
方法更具体。但是,如果将对象传递给使用
IEnumerable
参数的方法,它们可能会调用错误的方法

通过使用
AsEnumerable()
AsQueryable()
方法开始使用另一种方法,您也可以使用这种方式来获得优势。例如,
var-groupedPeople=users.Where(user=>user.Age>15)。AsEnumerable().GroupBy(user=>user.Age);
将通过数据库查询下拉正确的用户,然后在本地对对象进行分组


正如其他人所说,值得重复的是,在开始枚举序列(使用
foreach
)之前,什么都不会发生。现在您应该明白为什么不能采用其他方式:如果一次检索所有结果,您就无法建立查询以转换为更高效的查询(如SQL查询).

取消删除我的答案,因为我刚刚测试了它,它与我描述的完全一样:


上述查询都不会命中数据库,因为没有枚举。
IQueryable
查询和
IEnumerable
查询之间的区别在于,在
IQueryable
的情况下,将在数据库服务器上执行筛选,而在
IEnumerable
的情况下,将加载所有对象从数据库到内存,过滤将在.NET代码(linq到对象)中完成。您可以想象,这通常是性能杀手

我在我的项目中编写了简单测试:

[TestMethod]
public void Test()
{
    // ObjectQuery<Department> converted ot IEnumerable<Department>
    IEnumerable<Department> departmetns = CreateUnitOfWork().GetRepository<Department>().GetQuery();
    // No query execution here - Enumerable has also deffered exection
    var query = departmetns.Where(d => d.Id == 1); 
    // Queries ALL DEPARTMENTS here and executes First on the retrieved result set
    var result = departmetns.First(); 
}
[TestMethod]
公开无效测试()
{
//ObjectQuery转换为IEnumerable
IEnumerable departmetns=CreateUnitOfWork().GetRepository().GetQuery();
//此处没有查询执行-Enumerable也有不同的执行
var query=departmetns.Where(d=>d.Id==1);
//在此处查询所有部门,并首先对检索到的结果集执行
var result=departemetns.First();
}

不同之处在于,IEnumerable执行多个过滤器,一次一个。例如,从100个元素中,第一个过滤器将输出20个,然后第二次过滤所需的10个。它将对数据库进行一次查询,但会下载不必要的数据。使用IQueryable将通过一次查询再次下载,但仅下载一次所需的10项。以下链接提供了这些查询如何工作的一些优秀示例:

因此,当使用
IEnumerable
时,它将立即命中数据库,并将从users表中请求所有行,或仅请求年龄设置为32岁的行?“上述查询都不会命中数据库,因为没有枚举”与前两个答案相矛盾。到目前为止,我从你那里得到了非常好的答案,所以我不得不更认真地对待你的答案。仍然真的“没有枚举”?
IEnumerable
在调用
时(u=>u.Age==32)
没有枚举?这是怎么回事(我可以想象它的工作原理类似于
IQueryable
,但知道比猜测更好)?我测试了它并取消了删除我的答案,因为在SQL Profiler中检查后,我发现我的答案是正确的。正如我说的,我第一次认真对待它……所以当我调用
Where(u=>u.Age==32)时
在一些
IEnumerable
上,它不打算枚举,而只是创建新的枚举,引用原始的枚举和附加的一些“where”过滤器?或者它是如何工作的?也许这应该是另一个问题……我无法回答它是如何工作的,但对我来说是有意义的(都
IEnumerable)
IEnumerable<User> usersEnumerable = db.UserSet;
IQueryable<User> usersQueryable = db.UserSet;

var users = /* one of usersEnumerable or usersQueryable */;

var age32StartsWithG = users.Where(user => user.Age == 32)
                            .Where(user => user.Name.StartsWith("G");
[TestMethod]
public void Test()
{
    // ObjectQuery<Department> converted ot IEnumerable<Department>
    IEnumerable<Department> departmetns = CreateUnitOfWork().GetRepository<Department>().GetQuery();
    // No query execution here - Enumerable has also deffered exection
    var query = departmetns.Where(d => d.Id == 1); 
    // Queries ALL DEPARTMENTS here and executes First on the retrieved result set
    var result = departmetns.First(); 
}