My ASP.NET MVC 4 application uses Entity Framework v5, the Ninject and Ninject.MVC3 nuget packages, and data is being stored in SQL Server Express. Models were generated using the "EF 5.x DbContext Generator for C#" template. Lazy Loading Enabled is set to True in my edmx.
I'm using the repository pattern, with my repository and context living in a separate project in my solution that is referenced by the ASP.NET MVC 4 project.
So, the problem -- after saving a new object ("Trade") that's a property of a view model, I query the repository for that object. At that point, the navigation properties I would expect to be populated are null. See the comment in the Create() method below.
If I retrieve an existing Trade from the db (one that I didn't just save), all the navigation properties seem to be populated.
I found a report of a similar/identical problem on this page. The author of the article states, "I think this is a glitch in DbContext. Namely, Lazy loading for the foreign key navigation property doesn’t work for the newly added item, but the lazy loading for the navigation property in the many end works fine, such as Teacher.Classes. This glitch occurs only for the newly added item. If you don’t load Class.Teacher explicitly above for the newly added item, it will be null if it hasn’t been loaded somewhere in Entity Framework. However, if it is loaded already somewhere, then C.Teacher can be automatically resolved by Entity Framework. Whereas, for ObjectContext, lazy loading is fine for all types of navigation properties."
My controller's Create method looks like this:
[HttpPost]
public ActionResult Create(TradeViewModel tradeViewModel)
{
if (ModelState.IsValid)
{
_employeesRepository.SaveTrade(tradeViewModel.Trade);
var trade =
_employeesRepository.Trades.First(
x =>
x.RequesterId == tradeViewModel.Trade.RequesterId &&
x.RequesterWorkDate == tradeViewModel.Trade.RequesterWorkDate);
// Null reference encountered below, as trade.TradeType and trade.Employee are both null
String userMessage = "New " + trade.TradeType.TradeTypeDescription + " requested with '" + ControllerHelpers.GetDisplayName(trade.Employee) + "'";
TempData["UserMessage"] = userMessage;
return RedirectToAction("Index");
}
return View();
}
The SaveTrade() method in the employee repository looks like:
public void SaveTrade(Trade trade)
{
var data = (from t in _context.Trades
where t.RequesterId == trade.RequesterId
&& t.RequesterWorkDate == trade.RequesterWorkDate
select t);
if (!data.Any())
{
_context.Trades.Add(trade);
}
_context.SaveChanges();
}
And finally, Trades in _employeesRepository looks like:
public IQueryable<Trade> Trades
{
get { return _context.Trades; }
}