Skullomania
Skullomania

Reputation: 2215

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.

Upvotes: 8

Views: 1944

Answers (5)

Jon Egerton
Jon Egerton

Reputation: 41539

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.

Upvotes: 4

JunaidKirkire
JunaidKirkire

Reputation: 918

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.

Upvotes: 0

Dave Bish
Dave Bish

Reputation: 19646

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

Upvotes: 1

Thaoden
Thaoden

Reputation: 3580

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.

Upvotes: 2

Matt Burland
Matt Burland

Reputation: 45135

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.

Upvotes: 5

Related Questions