Completely revised:
Okay, I'm using Ninject with the MVC 2 extension as my DI container, and AutoMapper as my entity <--> view model mapper. I'm getting an 'ObjectContext is disposed' error in my view model -> entity mapping. My code is below.
Ninject bindings:
public class DIModule : NinjectModule
{
public override void Load()
{
this.Bind<HGEntities>().ToSelf().InRequestScope();
this.Bind<IArticleRepository>().To<HGArticleRepository>().InRequestScope();
this.Bind<IGameRepository>().To<HGGameRepository>().InRequestScope();
this.Bind<INewsRepository>().To<HGNewsRepository>().InRequestScope();
this.Bind<ErrorController>().ToSelf().InRequestScope();
this.Bind<HGController>().ToSelf().InRequestScope();
}
}
My repository:
public class HGGameRepository : IGameRepository, IDisposable
{
private HGEntities _context;
public HGGameRepository(HGEntities context)
{
this._context = context;
}
// methods
public void SaveGame(Game game)
{
if (game.GameID > 0)
{
_context.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Modified);
}
else
{
_context.Games.AddObject(game);
}
_context.SaveChanges();
}
public void Dispose()
{
if (this._context != null)
{
this._context.Dispose();
}
}
}
My controller's constructor, which includes my AutoMapper map definitions:
public AdminController(IArticleRepository articleRepository, IGameRepository gameRepository, INewsRepository newsRepository)
{
_articleRepository = articleRepository;
_gameRepository = gameRepository;
_newsRepository = newsRepository;
Mapper.CreateMap<Game, AdminGameViewModel>()
.BeforeMap((s, d) =>
{
int platCount = s.Platforms.Count;
var plats = s.Platforms.ToArray();
d.PlatformIDs = new int[platCount];
for (int i = 0; i < platCount; ++i)
{
d.PlatformIDs[i] = plats[i].PlatformID;
}
})
.ForMember(dest => dest.Pros, opt => opt.MapFrom(src => src.Pros.Split(new char[] {'|'})))
.ForMember(dest => dest.Cons, opt => opt.MapFrom(src => src.Cons.Split(new char[] {'|'})))
.ForMember(dest => dest.PlatformIDs, opt => opt.Ignore());
Mapper.CreateMap<AdminGameViewModel, Game>()
.BeforeMap((s, d) =>
{
if (d.Platforms != null && d.Platforms.Count > 0)
{
var oldPlats = d.Platforms.ToArray();
foreach (var oldPlat in oldPlats)
{
d.Platforms.Remove(oldPlat);
}
}
foreach (var platId in s.PlatformIDs)
{
var plat = _gameRepository.GetPlatform(platId);
d.Platforms.Add(plat);
}
})
.ForMember(dest => dest.Platforms, opt => opt.Ignore())
.ForMember(dest => dest.BoxArtPath, opt => opt.Ignore())
.ForMember(dest => dest.IndexImagePath, opt => opt.Ignore())
.ForMember(dest => dest.Cons, opt => opt.MapFrom(src => string.Join("|", src.Cons)))
.ForMember(dest => dest.Pros, opt => opt.MapFrom(src => string.Join("|", src.Pros)))
.ForMember(dest => dest.LastModified, opt => opt.UseValue(DateTime.Now));
}
It's the second mapping that's important here.
Next is my Edit method:
[HttpPost]
public ActionResult EditGame([Bind(Prefix="GameData")]AdminGameViewModel formData)
{
Game game = _gameRepository.GetGame(formData.GameID);
if (ModelState.IsValid)
{
game = AutoMapper.Mapper.Map<AdminGameViewModel, Game>(formData, game);
// it dies here, so the rest of the method is immaterial
}
Finally, the stack trace:
[ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.]
System.Data.Objects.ObjectContext.EnsureConnection() +87
System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) +90
System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +96
System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +182
System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1(IEnumerable`1 sequence) +74
System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable`1 query, Expression queryRoot) +95
System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) +163
System.Linq.Queryable.FirstOrDefault(IQueryable`1 source, Expression`1 predicate) +300
HandiGamer.Domain.Concrete.HGGameRepository.GetPlatform(Int32 id) in C:\Users\Kevin\documents\visual studio 2010\Projects\HandiGamer\HandiGamer.Domain\Concrete\HGGameRepository.cs:68
HandiGamer.WebUI.Controllers.AdminController.<.ctor>b__a(AdminGameViewModel s, Game d) in C:\Users\Kevin\documents\visual studio 2010\Projects\HandiGamer\HandiGamer\Controllers\AdminController.cs:56
AutoMapper.<>c__DisplayClass1b.<BeforeMap>b__1a(Object src, Object dest) +139
AutoMapper.TypeMap.<get_BeforeMap>b__0(Object src, Object dest) +118
AutoMapper.Mappers.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper) +196
AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) +256
AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) +459
[AutoMapperMappingException:
Mapping types:
AdminGameViewModel -> Game
HandiGamer.WebUI.ViewModels.AdminGameViewModel -> HandiGamer.Domain.Entities.Game
Destination path:
Game
Source value:
HandiGamer.WebUI.ViewModels.AdminGameViewModel]
AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) +537
AutoMapper.MappingEngine.Map(Object source, Object destination, Type sourceType, Type destinationType, Action`1 opts) +179
AutoMapper.MappingEngine.Map(TSource source, TDestination destination, Action`1 opts) +190
AutoMapper.MappingEngine.Map(TSource source, TDestination destination) +146
AutoMapper.Mapper.Map(TSource source, TDestination destination) +105
HandiGamer.WebUI.Controllers.AdminController.EditGame(AdminGameViewModel formData) in C:\Users\Kevin\documents\visual studio 2010\Projects\HandiGamer\HandiGamer\Controllers\AdminController.cs:323
lambda_method(Closure , ControllerBase , Object[] ) +162
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +51
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +409
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +52
System.Web.Mvc.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a() +127
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +436
System.Web.Mvc.<>c__DisplayClassf.<InvokeActionMethodWithFilters>b__c() +61
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +305
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830
System.Web.Mvc.Controller.ExecuteCore() +136
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +111
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +65
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +42
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +141
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +54
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +52
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +690
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +194
Following the process in the debugger, my ObjectContext's (HGEntities) connection remains intact until my view model -> game map is invoked. For some reason, the connection is disposed at that point. Any ideas as to why that's happening?