IQueryable的,签单,IEnumerator的之间的差异? [英] Differences between IQueryable, List, IEnumerator?

查看:135
本文介绍了IQueryable的,签单,IEnumerator的之间的差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道的是不同IQueryable的,列表,之间的IEnumerator什么时候我应该使用每个吗?

I am wondering what the different is between IQueryable, List, IEnumerator and when I should using each one?

例如使用LINQ时为sql我会做这样的事情。

For instance when using linq to sql I would do something like this

public List<User> GetUsers()
{
   return db.User.where(/* some query here */).ToList();
}

现在我想知道我是否应该使用IQueryable的,而不是,但我不能确定使用它在列表的优势。

now I am wondering if I should be using IQueryable instead but I am unsure of the advantages of using it over the list.

推荐答案

的IQueryable&LT; T&GT; 旨在允许查询提供商(例如,像LINQ的ORM来SQL或实体框架)使用包含在查询前pressions翻译请求转换为其他格式。换句话说,LINQ到SQL着眼于在您使用随你正在做的比较实体的属性和实际创建一个SQL语句前preSS(希望)等效的请求。

IQueryable<T> is intended to allow a query provider (for example, an ORM like LINQ to SQL or the Entity Framework) to use the expressions contained in a query to translate the request into another format. In other words, LINQ-to-SQL looks at the properties on the entities that you're using along with the comparisons you're making and actually creates a SQL statement to express (hopefully) an equivalent request.

的IEnumerable&LT; T&GT; 是更通用比的IQueryable&LT; T&GT; (虽然<$ C $的所有实例C>的IQueryable&LT; T&GT; 实施的IEnumerable&LT; T&GT; ),并只定义序列。不过,也有定义该接口上的某些查询型运营商和使用普通code,以评估这些条件的可枚举类中提供扩展方法。

IEnumerable<T> is more generic than IQueryable<T> (though all instances of IQueryable<T> implement IEnumerable<T>) and only defines a sequence. However, there are extension methods available within the Enumerable class that define some query-type operators on that interface and use ordinary code to evaluate these conditions.

列表&LT; T&GT; 只是一个输出格式,同时它实现的IEnumerable&LT; T&GT; ,是不是直接相关的查询。

List<T> is just an output format, and while it implements IEnumerable<T>, is not directly related to querying.

在换句话说,当你使用的IQueryable&LT; T&GT; ,你定义和的前pression 的那个被转换成别的东西。即使你写code,即code从来没有得到的执行的,它只是变得的检查的,变成别的东西,比如一个实际的SQL查询。正因为如此,只有某些事情是这些前pressions内有效。举例来说,你不能叫你从这些前pressions中定义一个普通函数,因为LINQ到SQL不知道如何把你的电话到一个SQL语句。大多数这些限制,在运行时只计算,很遗憾。

In other words, when you're using IQueryable<T>, you're defining and expression that gets translated into something else. Even though you're writing code, that code never gets executed, it only gets inspected and turned into something else, like an actual SQL query. Because of this, only certain things are valid within these expressions. For instance, you cannot call an ordinary function that you define from within these expressions, since LINQ-to-SQL doesn't know how to turn your call into a SQL statement. Most of these restrictions are only evaluated at runtime, unfortunately.

当您使用的IEnumerable&LT; T&GT; 进行查询,你使用LINQ到对象,这意味着你正在写的实际code用于评估您的查询或转换的结果,所以有,一般来说,你可以做什么,没有任何限制。您可以自由这些前pressions内调用等功能。

When you use IEnumerable<T> for querying, you're using LINQ-to-Objects, which means you are writing the actual code that is used for evaluating your query or transforming the results, so there are, in general, no restrictions on what you can do. You can call other functions from within these expressions freely.

使用LINQ到SQL

去手牵手与上面的区别,这也是很重要的是要记住这是如何工作了实践中。当你写针对LINQ数据上下文类到SQL查询时,它会产生一个的IQueryable&LT; T&GT; 。不管你做什么的的IQueryable&LT; T&GT; 本身的是会得到变成SQL,所以你的过滤和转换将在服务器上完成。不管你做什么反对为的IEnumerable&LT此的; T&GT; 的,将在应用层进行。有时候,这是可取的(在你需要使用客户端code,例如的情况下),但在许多情况下,这是无意的。

Going hand-in-hand with the distinction above, it's also important to bear in mind how this works out in practice. When you write a query against a data context class in LINQ to SQL, it produces an IQueryable<T>. Whatever you do against the IQueryable<T> itself is going to get turned into SQL, so your filtering and transformation will be done on the server. Whatever you do against this as an IEnumerable<T>, will be done at the application level. Sometimes this is desirable (in the case where you need to make use of client-side code, for example), but in many cases this is unintentional.

例如,如果我有一个客户上下文产权重组presenting一个客户表,而且每个客户都有一个客户ID 列,让我们来看看两种方式来做到这一点查询:

For example, if I had a context with a Customers property representing a Customer table, and each customer has a CustomerId column, let's look at two ways to do this query:

var query = (from c in db.Customers where c.CustomerId == 5 select c).First();

这将产生SQL,查询的客户数据库客户ID 等于5.喜欢的东西记录:

This will produce SQL that queries the database for the Customer record with a CustomerId equaling 5. Something like:

select CustomerId, FirstName, LastName from Customer where CustomerId = 5

现在,如果我们把的客户怎么办的IEnumerable&LT;客户&GT; 使用 AsEnumerable()扩展方法?

Now, what happens if we turn Customers into an IEnumerable<Customer> by using the AsEnumerable() extension method?

var query = (from c in db.Customers.AsEnumerable() where c.CustomerId == 5 select c).First();

这个简单的变化有一个严重后果。由于我们转向客户的IEnumerable&LT;客户&GT; ,这将带来整个表背和过滤它客户端(当然,严格来说这将带回每一行表中的,直到遇到一个适合的条件而定的,但有一点是相同的)。

This simple change has a serious consequence. Since we're turning Customers into an IEnumerable<Customer>, this will bring the entire table back and filter it on the client side (well, strictly speaking this will bring back every row in the table until it encounters one that fits the critiera, but the point is the same).

了ToList()

到现在为止,我们只谈到了的IQueryable 的IEnumerable 。这是因为它们是相似的,免费的接口。在这两种情况下,你定义的查询的;也就是说,你定义的其中的查找数据,的什么的过滤器适用,而什么的数据返回。这两者都是查询

Up until now, we've only talked about IQueryable and IEnumerable. This is because they are similar, complimentary interfaces. In both cases, you're defining a query; that is, you're defining where to find the data, what filters to apply, and what data to return. Both of these are queries

query = from c in db.Customers where c.CustomerId == 5 select c;
query = from c in db.Customers.AsEnumerable() where c.CustomerId == 5 select c;

就像我们已经谈到,第一个查询使用的IQueryable 第二个使用的IEnumerable 。在这两种情况下,但是,这仅仅是一个的查询的。定义查询实际上并没有做到对数据源什么。当code开始遍历列表中实际执行的查询。这可能发生多种方式;一个的foreach 循环,调用了ToList()

Like we've talked about, the first query is using IQueryable and the second uses IEnumerable. In both cases, however, this is just a query. Defining the query doesn't actually do anything against the data source. The query is actually executed when code begins to iterate over the list. This can happen multiple ways; a foreach loop, calling ToList(), etc.

执行查询的第一个的和的每个的时间它的迭代。如果你打电话给了ToList()查询两次,你最终会得到两个列表具有完全不同的对象。它们可能包含相同的数据,但它们将是不同的引用。

The query is executed the first and every time it's iterated. If you were to call ToList() on query two times, you would end up with two lists with completely distinct objects. They might contain the same data, but they would be different references.

的意见后修改

我只是想清楚当事情在客户端完成,当他们完成服务器端之间的区别。如果你引用的是的IQueryable&LT; T&GT; 的IEnumerable&LT; T&GT; 完成查询的之后的它是一个的IEnumerable&LT; T&GT; 将在客户端完成。例如,假设我有这样的表和LINQ到SQL方面:

I just want to be clear about the distinction between when things are done client-side and when they're done server-side. If you're referencing an IQueryable<T> as an IEnumerable<T>, only the querying done after it's an IEnumerable<T> will be done client-side. For example, say I have this table and a LINQ-to-SQL context:

Customer
-----------
CustomerId
FirstName
LastName

我第一次构建基于查询。这将创建一个的IQueryable&LT;客户&GT;

var query = from c in db.Customers where c.FirstName.StartsWith("Ad") select c;

现在我通过该查询,需要一个功能的的IEnumerable&LT;客户&GT; 并执行基于姓:

Now I pass that query to a function that takes an IEnumerable<Customer> and does some filtering based on LastName:

public void DoStuff(IEnumerable<Customer> customers)
{
    foreach(var cust in from c in customers where c.LastName.StartsWith("Ro"))
    {
        Console.WriteLine(cust.CustomerId);
    }
}

我们已经做了第二次查询在这里,但它被上的IEnumerable&LT完成;客户&GT; 。这是怎么回事在这里发生的是,第一个查询将被评估,运行该SQL:

We've done a second query here, but it's being done on an IEnumerable<Customer>. What's going to happen here is that the first query will be evaluated, running this SQL:

select CustomerId, FirstName, LastName from Customer where FirstName like 'Ad%'

所以,我们要带回大家谁的开始以广告。请注意,没有什么这里关于。这是因为它是被过滤掉的客户端。

So we're going to bring back everyone who's FirstName starts with "Ad". Note that there's nothing in here about LastName. That's because it's being filtered out client-side.

一旦它带回这些结果,该方案将随后遍历结果,并只提供其中的记录与罗启动。这样做的缺点是,我们带回来的数据 - 即,所有行的的开始与 RO - 即可以的已经过滤掉了在服务器上

Once it brings back these results, the program will then iterate over the results and deliver only the records whose LastName starts with "Ro". The downside to this is that we brought back data--namely, all rows whose LastName doesn't start with "Ro"--that could have been filtered out on the server.

这篇关于IQueryable的,签单,IEnumerator的之间的差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆