Tony, With once again a cursory glance.
Not sure it looks like it should work.... the pattern we are following is: ObjectContext dbContext = ((IObjectContextAdapter)db).ObjectContext; var set = dbContext.CreateObjectSet<TimesheetItem>(); set.MergeOption = MergeOption.NoTracking and then building the query after that..... Neil. On 27 September 2012 13:50, Tony Wright <tonyw...@gmail.com> wrote: > Thanks Michael and Neil. > > Michael, I understand your point about ensuring that only the required data > is returned to the client, however in this case I am happy for the lot to be > returned. > > It seems like a bit of a hack to go through and detach every object. In > fact, I probably wouldn't recommend that to anyone, although I'm sure it has > its use! > > I went to the EF5 designer, right clicked, properties, then set the property > Lazy Loading Enabled to false, and it now works without needing a separate > POCO object. I don't know how happy I am about that, though, as I lose the > benefits of lazy loading! > > So I thought I'd have a go at the MergeOption.Notracking version. > > It wouldn't let me cast my query to an ObjectQuery, because my EF database > context is a DbContext. > > So I cast it: > ObjectContext dbContext = > ((IObjectContextAdapter)db).ObjectContext; > > var set = dbContext.CreateObjectSet<TimesheetItem>(); > > var result = from ti in set > where ti.StaffId == staffId && ti.TimesheetPeriodId > == timesheetPeriodId > orderby ti.StartTime, ti.ForDate > select ti; > > ObjectQuery<TimesheetItem> query = > (ObjectQuery<TimesheetItem>)result; > > var queryResult = query.Execute(MergeOption.NoTracking); > > List<TimesheetItem> listOfTimesheetItems = queryResult.ToList(); > return Json(new { TimesheetItems = listOfTimesheetItems }); > > Unfortunately, that doesn't work either. All referenced objects are lazy > loaded. Hmmm. > > Is there something I'm missing here? > > T. > > > -----Original Message----- > From: ozdotnet-boun...@ozdotnet.com [mailto:ozdotnet-boun...@ozdotnet.com] > On Behalf Of Neil Young > Sent: Thursday, 27 September 2012 11:45 AM > To: ozDotNet > Subject: Re: JSON issue MVC4.5, EF5 > > Without lookig very hard I would suggest that Lazy Loading is not your > friend here and the serialization is walking your object graph and failing. > > Few options you can run with query with: > 1. a MergeOption of NoTracking > (http://blogs.msdn.com/b/dsimmons/archive/2010/01/12/ef-merge-options-and-co > mpiled-queries.aspx) > 2. or you can turn lazy loading off > m_objectContext.ContextOptions.LazyLoadingEnabled > 3. Or you can simply detach the object before returning it (but if you have > any releated objects then detach will simply remove them from your object so > they won't travel down in the serialisation). > > Either way you are going to need to make sure that everything you want has > already been loaded ie any related objects- either with a strategy at query > time or by explicitly loading those sub tables. > > Hope that helps. > > Neil. > > On 27 September 2012 10:30, Tony Wright <tonyw...@gmail.com> wrote: >> Hi all, >> >> >> >> Can someone please tell me the problem with using EF5 generated model >> classes when passing data using JSON calls? >> >> >> >> If I call an EF query and retrieve some EF generated classes with >> references to other classes, then if I try to pass them directly back >> to the view via a JSON call, they fail. >> >> >> >> If I retrieve the classes via the EF query, populate my own stripped >> down >> (POCO) classes, and pass my stripped down classes back to the view via >> a JSON call, they succeed. >> >> >> >> Is there a trick to using the EF classes all the way through, or is >> this supposed to be a bad practice and I am supposed to create POCO >> classes every time? >> >> >> >> Regards, >> >> Tony >> >> >> >> >> >> Example code. The first is a Go button that I click that passes a >> staffId and a timesheetPeriodId to the controller. It is meant to >> return a subset of timesheet items. >> >> >> >> <script src="/Scripts/jquery-1.7.1.min.js" >> type="text/javascript"></script> >> >> <script> >> >> $(function () { >> >> $('#GoButton').click(function () { >> >> var url = '@Url.Action("LoadNewTimesheet", "Timesheet")'; >> >> $.post(url, { staffId: $('#staff').val(), timesheetPeriodId: >> $('#period').val() }, >> >> function(data) { >> >> viewModel.LoadTimesheetComplete(data); >> >> }); >> >> >> >> } >> >> ) >> >> }); >> >> </script> >> >> >> >> Here is the controller code that works. It basically retrieves the >> timesheet items from the database, populates poco classes, then passes >> the poco classes back to the view. >> >> >> >> [HttpPost] >> >> public ActionResult LoadNewTimesheet(int staffId, int >> timesheetPeriodId) >> >> { >> >> List<JsonTimesheetItem> listOfTimesheetItems = new >> List<JsonTimesheetItem>(); >> >> >> >> List<TimesheetItem> returnedList = >> db.TimesheetItem.Where(ti => ti.StaffId == staffId && >> ti.TimesheetPeriodId == timesheetPeriodId) >> >> .OrderBy(ti => >> ti.StartTime).OrderBy(ti => ti.ForDate).ToList(); >> >> >> >> foreach (TimesheetItem ti in returnedList) >> >> { >> >> listOfTimesheetItems.Add(new JsonTimesheetItem() >> >> { >> >> TimesheetItemId = ti.TimesheetItemId, >> >> TimesheetPeriodId = ti.TimesheetPeriodId, >> >> ForDate = ti.ForDate, >> >> TaskId = ti.TaskId, >> >> StartTime = ti.StartTime, >> >> EndTime = ti.EndTime, >> >> NonWorkTime = ti.NonWorkTime, >> >> AdditionalNotes = ti.AdditionalNotes, >> >> IsLocked = ti.IsLocked, >> >> ApprovalStatusId = ti.ApprovalStatusId, >> >> Hours = ti.Hours, >> >> ImportTaskName = ti.ImportTaskName, >> >> StaffId = ti.StaffId, >> >> IsDailyRate = ti.IsDailyRate >> >> }); >> >> } >> >> >> >> return Json(new { TimesheetItems = listOfTimesheetItems >> }); >> >> } >> >> >> >> On the other hand, the following fails when populated, I think because >> other classes referenced within the TimesheetItem class somehow screw >> up JSON, and the success function in javascript never gets called. >> >> >> >> [HttpPost] >> >> public ActionResult LoadNewTimesheet(int staffId, int >> timesheetPeriodId) >> >> { >> >> List<TimesheetItem> returnedList = >> db.TimesheetItem.Where(ti => ti.StaffId == staffId && >> ti.TimesheetPeriodId == timesheetPeriodId) >> >> .OrderBy(ti => >> ti.StartTime).OrderBy(ti => ti.ForDate).ToList(); >> >> >> >> return Json(new { TimesheetItems = returnedList }); >> >> } >> >> >> >> Do I have to create POCO classes every time? Apart from what I see as >> an unnecessary extra layer of processing, maintenance and (small) >> performance hit, I find them annoying! >> >> >> >> >