Ras*_*sto 7 .net c# ienumerable entity-framework iqueryable
据我所知,当我使用LINQ扩展方法(使用lambda表达式语法)时IQueryable,实际上ObjectSet它们被转换为LINQ to SQL查询.我的意思是那个命令
IQueryable<User> users = db.UserSet;
var users32YearsOld = users.Where(user => user.Age == 32);
Run Code Online (Sandbox Code Playgroud)
与...完全相同
IQueryable<User> users = db.UserSet;
var users32YearsOld = from user in users where user.Age == 32 select user;
Run Code Online (Sandbox Code Playgroud)
因此,它们users32YearsOld不会在数据库中出现,直到它们被枚举为循环等.(希望我能正确理解这一点).
但是,到底是怎么回事,如果我不掩盖这样的事情发生ObjectSet的IQueryable,但作为IEnumerable?那么它的类型是IEnumerable什么?
IEnumerable<User> users = db.UserSet;
var users32YearsOld = users.Where(user => user.Age == 32);
Run Code Online (Sandbox Code Playgroud)
它会立即打到数据库(如果是这样的话,那么?在第一行或第二行)?或者它是否会像上一个命令一样,users32YearsOld在枚举之前不会命中数据库?如果我使用以下代码会有什么不同吗?
IEnumerable<User> users = db.UserSet;
var users32YearsOld = from user in users where user.Age == 32 select user;
Run Code Online (Sandbox Code Playgroud)
谢谢
Lad*_*nka 12
取消我的答案,因为我刚测试它,它完全按照我的描述工作:
由于没有枚举,因此没有提到的查询将访问数据库.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();
}
Run Code Online (Sandbox Code Playgroud)
这是一个简单的解释:
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");
Run Code Online (Sandbox Code Playgroud)
如果你使用usersEnumerable,当你开始枚举它时,两个Wheres将按顺序运行; 首先,ObjectSet将获取所有对象,对象将被过滤到32岁的对象,然后这些将被过滤到名称以G开头的那些对象.
如果你使用usersQueryable,那么两个Wheres将返回将累积选择标准的新对象,当你开始枚举它时,它会将所有条件转换为查询.这会产生显着的差异.
通常,您不必担心,因为您要么声明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查询).
| 归档时间: |
|
| 查看次数: |
7808 次 |
| 最近记录: |