简体   繁体   中英

In ASP.Net MVC should I add my where clause to my ienumerable or iqueryable when implementing search?

I was wondering when a user goes to an index page for a table on my website and uses a search function should I add my where clause to the ienumerable or iqueryable? I know both can be done but which one is more efficient and can I add a custom search string extension to a iqueryable ?

Adding it to the IQueryable will add it to the query that goes to the database since it's part of a live connection to the DB.

Adding it to an IEnumerable(that is not of type IQueryable) will do the filtering in memory after the query has executed.

If you're dealing with an underlying IQueryable, in both cases, I doubt there will be a difference. However, I recommend viewing the resulting queries in a sql profiler to ensure you are executing the expected queries.

I'd add it to your IQueryable just in case, but since both are interfaces, it may not really matter. If your IEnumerables are always IQueryables, you should still get the benefits of your queries being run on the database and not after the database returns results.

IQueryable and IEnumerable are what's called "interfaces". An interface defines an API that the actual object should be able to respond to, while allowing for a degree of variability in the actual type (read: class that the object implements). As long as the type implements the interface, everything just works, and you can (for the most part) swap one type for another as long as they all implement the same interface(s).

That said, IQueryable is actually an extension of IEnumerable , so for the purposes of what you're talking about here, they're practically the same thing. In other words, it's not about whether the returned object set from the database is cast to an IQueryable or an IEnumerable ; in either case, the query may or may not have been executed yet, as neither interface dictates that the query must be executed. What does matter is whether you've done something in the code that would cause the query to be executed: things like casting to a list ( .ToList() ) or iterating over the result set ( for , foreach , etc.), etc. Running a count will also execute the query, but for a slightly different reason (you'll issue a COUNT query to the database instead of a SELECT).

The moral is that you just need to pay attention to which parts of your code will actually cause the query to be executed and make sure any query alterations occur before that point.

From your description of the situation I'd use an IQueryable to run your Where() 's against then cast it as a List<SomeViewModel> to return it to your page. Doing this will defer execution of the query against the database until you've refined it to return just what you need.

Instead of custom search string extensions I use plain old variables and pare down my object depending on what gets passed in. So if you're writing a search controller that takes in firstName and lastName as parameters you'd do something like:

IQueryable<User> users = Context.Users;

if (firstName != null)
    users = users.Where(x => x.FirstName == firstName);

if(lastName != null)
    users = users.Where(x => x.LastName == lastName);

List<SearchResultViewModel> model = users.Select(x => new SearchResultViewModel
        {
            FirstName = x.FirstName,
            LastName = x.LastName,
            JobTitle = x.JobTitle
            // and so forth for whatever fields you need to return...
        }).ToList();
        // The ToList() will cause the query to be 
        // evaluated and executed.

Naturally, you should check to make sure at least one of your search fields has something in it so you don't return the whole table's worth of data. From here you can rig it to accept variables for pagination, apply sorting, all kinds of fun stuff.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM