简体   繁体   中英

Need help understanding LINQ in MVC?

I am quite new to MVC from webforms and it has been a really, really steep learning curve for me. Here is the function in the tutorial that I am following:

public ActionResult Index(string id)
{
    string searchString = id;
    var movies = from m in db.Movies
                 select m;
    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }
    return View(movies);
}

Here is what I think I know that is happening. The method being an Action result(without parameters) re returning a view. The parameters are added to tell the application to look for a "id" string.

I find the lambda statement a little easier to understand. The if is checking to see if the searchString is null if not it returns the movie that matches the description in searchString .

In the method however, searchString is given the value of id in the parameter. Here is where I start getting lost, right after searchString is defined, a LINQ statement is placed inside the variable movies . In that statement, what is the purpose of m ? Why is it not defined or is it? The same with the s in the lambda.

Both m and s are implicitly typed. Since you are selecting m from movies , you don't need to tell LINQ what m is. It can imply the type by looking at what db.Movies is a collection of. So if db.Movies was IEnumerable<Movie> (for example) then m would be a Movie .

There is nothing to stop you from specifying the type if you really want to, so you could type:

 var movies = from Movie m in db.Movies
             select m;

But you rarely need to.

Note you are also implicitly typing movies , it's the same concept. So long as the compiler can unambiguously figure out what the type should be.

The variables m and s are variables for each instance of Movie within the db.Movies "collection" (I assume that's what the class is called).

Conceptually these are similar to using and sql alias m in the following sql:

select m.* from Movies m

When you later apply the where clause you're conceptually ending up with:

select * from (
    select m.* from Movies m
) s
where s.Title like '%' + searchString + '%'

NOTE that this isn't how the sql actually ends up when it runs against the database, just a representation to aid understanding.

If you look at the value of movies then you'll see that it is an IQueryable or similar. This means that it hasn't actually executed yet - you've not returned anything. So adding the where clause later is fine - it just gets added to the query that'll get run later.

var movies = from m in db.Movies select m roughly translates to "Take all items in db.Movies and name them temporarily m, then return them in an IEnumerable". Indeed you'll see that movies is of type IEnumerable<Movie> .

The same goes for movies = movies.Where(s => s.Title.Contains(searchString)); : For all items in movies, name them temporarily s and return those whose Title contains your searchString as an IEnumerable .

I hope it became a bit clearer.

Ok - I'll try to explain what's happening:

with:

var movies = from m in db.Movies select m;

You are describing a way of processing the collection 'db.Movies' (whatever that is...)

In descriptive language:

1) in dbo.Movies We are going to be inspecting/looping over everything everything in db.Movies.

2) from m As we go over them, 1-by-1 we'll store each thing we come across in a variable called 'm' for further use in the expression.

3) select m Ok - we want this query / expression to actually return something - to actually yield some results - so, lets 1-by-1 just return the 'm' we declared earlier

The variables m and s are using the var keywords which means that you don't have to explicitly mention the type of the variable. The compiler figures it out for you. It's basically a variable of the IEnumerable type.

The var keyword is generally useful in the following when you cannot explicitly define the return type of movies as shown below-

var movies = from m in db.Movies
             select new { m.Attr1, m.Attr2 } ;

Since, the clause within new is another 'anonymous' object not specified anywhere, you need the var keyword.

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