Search code examples
c#asp.netentity-frameworkasp.net-mvc-4extension-methods

Why casting IQueryable to .toList() include data to object DbContext?


I have a code example that is using entity-framework

This one is working:

    public ActionResult Index()
    {
        BlogContext dbContext = new BlogContext();
        dbContext.Posts.Include(a => a.Tags).ToList();
        return View(dbContext.Posts.ToList());
    }

and this one is not:

    public ActionResult Index()
    {
        BlogContext dbContext = new BlogContext();
        dbContext.Posts.Include(a => a.Tags);
        return View(dbContext.Posts.ToList());
    }

So I do not understand, why only casting to List is enough to include tags from the model (List<Tags>), I would understand if it would be like this, which is fine too (and I am using that! Question is not about code formating!):

    public ActionResult Index()
    {
        BlogContext dbContext = new BlogContext();
        var model=dbContext.Posts.Include(a => a.Tags).ToList();
        return View(model);
    }

but it does not need to be. So my question is: Why casting IQueryable to toList is including data to object dbContext? I know that in entity-framework we are working with extensions but as far as I remember extensions return values not assign one to an object.

This is my partial view that is crashing:

@using BlogWeb.Models
@model Post


    <h1>@Model.Title</h1>
    <p class="lead">
        by <a href="#">1234</a>
    </p>
    <hr>
    <p>@Model.Created</p>
    <p class="lead">
        @Model.Body
    </p>
    @Html.Partial("_Tags", Model.Tags) -<< this is what is throwing error
    <hr>

And this is a partial tag view

@using BlogWeb.Models
@model List<Tag>
@foreach (Tag tag in Model)
{
    @Html.Label('#' + tag.TagName)
    @Html.Raw(" ")
}

Error message :

The model item passed into the dictionary is of type 'BlogWeb.Models.Post', but this dictionary requires a model item of type 'System.Collections.Generic.List`1[BlogWeb.Models.Tag]'.


Solution

  • When you are chaining those Linq methods together you're building up a query behind the scenes. Adding Include(...) tells it to join the other data on before executing. When you call ToList() the Linq query is executed with the Include(...).

    On the second example, you are not executing a query so when you call dbContext.Posts.ToList() it hasn't cached anything and is a different query that is getting executed without the Include(...).