Reputation: 13955
I'm not sure how to word the title of this question. I am learning Entity Framework in an MVC environment, and I am following along the Pluralsight lesson "Introduction to ASP.NET MVC 3". I've been building my solution along side the instructors, and so far, everything has gone well. But now I've hit a snag where I can't get something to work which he has working. I'll try and describe the snag:
Using Code-First, we are building a simple restaurant / review system. Here are the only two models we are using:
public class Restaurant
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual string ChefsName { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Review> Reviews { get; set; }
}
and
public class Review
{
public virtual int ID { get; set; }
public virtual Restaurant Restaurant { get; set; }
public virtual int Rating { get; set; }
public virtual string Body { get; set; }
public virtual DateTime Created { get; set; }
}
You'll notice that 'Review' has a reference back to Restaurant. The database created from these models looks like this:
Here's the view for Review:
<div class="review">
<h4>@Model.Restaurant.Name</h4>
<span>Rating: @Model.Rating</span>
<p>
@Model.Body
<span class="right">
@Html.ActionLink("Edit", "Edit", new { id = Model.ID })
</span>
</p>
The problem I'm having is here:
@Model.Restaurant.Name
"Restaurant" comes back null, so of course a Null Reference is thrown. Here's the Index portion of the controller:
public ActionResult Index()
{
var model = _db.Reviews.FindTheLatest(3);
return View(model);
}
And here's FindTheLatest()...
public static IEnumerable<Review> FindTheLatest(this IQueryable<Review> reviews, int numberOfReviews)
{
return reviews.OrderByDescending(r => r.Created).Take(numberOfReviews);
}
This is the query that is generated:
SELECT TOP (3)
[Extent1].[ID] AS [ID],
[Extent1].[Rating] AS [Rating],
[Extent1].[Body] AS [Body],
[Extent1].[Created] AS [Created],
[Extent1].[Restaurant_ID] AS [Restaurant_ID]
FROM [dbo].[Reviews] AS [Extent1]
ORDER BY [Extent1].[Created] DESC
In the teacher's online example, model.Restaurant seems to come back populated, as he gets no error. Not so for me.
It seems that I have the Restaurant_ID, but I'm not sure how/when/where Entity Framework would load the Restaurant model based on that ID. There seems to be something that I missed in building my solution along side his, but I don't know what it is.
I've downloaded his solution, but I'm having a hard time getting it to compile. (See this question). Yet, I've compared his code to mine, and I can't see why his is working and mine isn't. I'm hoping someone here can help me out.
Thanks!
Upvotes: 0
Views: 306
Reputation: 11964
You should use method Include
:
public ActionResult Index()
{
var model = _db.Reviews.Include(c=>c.Restaurant).FindTheLatest(3);
return View(model);
}
This method signal to EntityFramework that it should load Restaurant navigation property with Review
.
Upvotes: 2
Reputation: 12304
You need to include any related entities you want. Change this:
return reviews.OrderByDescending(r => r.Created).Take(numberOfReviews);
to this:
return reviews.Include(r => r.Restaurant).OrderByDescending(r => r.Created).Take(numberOfReviews);
https://msdn.microsoft.com/en-us/data/jj574232.aspx?f=255&MSPPError=-2147217396
Upvotes: 2