Differences when using IEnumerable and IQueryable as a type of ObjectSet

前端 未结 4 453
小蘑菇
小蘑菇 2021-02-09 08:19

As I understand it when I use LINQ extension methods (with lambda expression syntax) on IQueryable that is in the fact instance of ObjectSet they are t

相关标签:
4条回答
  • 2021-02-09 08:30

    Here's a simple explanation:

    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");
    

    If you use usersEnumerable, when you start enumerating over it, the two Wheres will be run in sequence; first the ObjectSet will fetch all objects and the objects will be filtered down to those of age 32, and then these will be filtered down to those whose name starts with G.

    If you use usersQueryable, the two Wheres will return new objects which will accumulate the selection criteria, and when you start enumerating over it, it will translate all of the criteria to a query. This makes a noticeable difference.

    Normally, you don't need to worry, since you'll either say var users or ObjectSet users when you declare your variable, which means that C# will know that you are interested in invoking the most specific method that's available on ObjectSet, and the IQueryable query operator methods (Where, Select, ...) are more specific than the IEnumerable methods. However, if you pass around objects to methods that take IEnumerable parameters, they might end up invoking the wrong methods.

    You can also use the way this works to your advantage by using the AsEnumerable() and AsQueryable() methods to start using the other approach. For example, var groupedPeople = users.Where(user => user.Age > 15).AsEnumerable().GroupBy(user => user.Age); will pull down the right users with a database query and then group the objects locally.

    As other have said, it's worth repeating that nothing happens until you start enumerating the sequences (with foreach). You should now understand why it couldn't be any other way: if all results were retrieved at once, you couldn't build up queries to be translated into a more efficient query (like an SQL query).

    0 讨论(0)
  • 2021-02-09 08:36

    The difference is that IEnumerable performs the filters if they are more, one at a time. For example, from 100 elements will output 20 by the first filter and then will filter second time the needed 10. It will make one query to the database but will download unnecessary data. Using IQueryable will download again with one query but only the required 10 items. The following link gives some excellent examples of how these queries work: https://filteredcode.wordpress.com/2016/04/29/ienumerable-vs-iqueryable-part-2-practical-questions/

    0 讨论(0)
  • 2021-02-09 08:46

    Undeleting my answer because I just tested it and it works exactly as I described:

    None of mentioned queries will hit the database because there was no enumeration. The difference between IQueryable query and IEnumerable query is that in the case of IQueryable the filtering will be executed on the database server whereas in the case of IEnumerable all objects will be loaded from the database to a memory and the filtering will be done in .NET code (linq-to-objects). As you can imagine that is usually performance killer.

    I wrote simple test in my project:

    [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(); 
    }
    
    0 讨论(0)
  • 2021-02-09 08:48

    You are correct about IQueryable. As for IEnumerable, it would hit the database immediately upon assigning IEnumerable user.

    There is no real difference between using Linq Extensions vs. syntax in the example you provided. Sometimes one or the other will be more convenient (see linq-extension-methods-vs-linq-syntax), but IMO it's more about personal preference.

    0 讨论(0)
提交回复
热议问题