2

完全改訂が配置されていますモデルマッパー。私のビューモデル - >エンティティマッピングで 'ObjectContextが破棄されました'というエラーが出ます。私のコードは以下の通りです。Ninject MVC 2、EF 4は、AutoMapperのObjectContextは

Ninjectバインディング:

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(); 
    } 
} 

マイリポジトリ:

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(); 
     } 
    } 
} 

私のコントローラのコンストラクター、私のAutoMapperマップの定義が含まれています

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)); 
    } 

それはここで重要なの第2のマッピングです。

[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 
    } 

最後に、スタックトレース:

次は私の編集方法であり、デバッガでプロセスに続いて

[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 

、私のObjectContextの(HGEntities)接続は、私の見解モデルまでそのまま残り - >ゲームマップが呼び出されます。何らかの理由で、接続はその時点で行われます。それがどうして起こっているのか、どんな考えですか?

+1

マッピングを手作業で試してみてください。それがうまくいくかどうかを確認してください。 – Omu

+1

なぜリポジトリにコンテキストを配置しますか?あなたはそうしてはいけません。 Ninjectがそれを処理させます。なぜコントローラのルールを定義するのですか?これは必要ではありません。 – LukLed

答えて

0

documentationに基づいて、実際には工場を使用することをお勧めしません。私はそれらを使用しますが、あなたの問題を解決する可能性があります。このエラーは、自分のDIの一点で冒険の旅を経て得られていましたが、なぜあなたがあなたのものを手に入れているのかは分かりません。私にとっては、関係や怠惰な読み込みによって引き起こされていました。遅延読み込みを有効にすると、オブジェクトはObjectContextへの参照を保持するので、関連するオブジェクトや関連するオブジェクトのコレクションを読み込むことができます。

最終的には、スタックトレースを投稿してエラーが発生した場合に、そのタイミングを正確に把握するのに役立ちます。

これが役に立ちます。

編集:問題は保存方法にあると思います。ゲームを編集するときにオブジェクトコンテキストを破棄した場合。あなたはAutoMapperから得たあなたの現在のゲームオブジェクトがどののObjectContextに添付されていない

_context.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Modified); 

:私はそれはあなたの行を参照してくださいObjectStateManagerになりますとは思いません。ここで私は更新のために使用する方法は次のとおりです。

public void Update(TEntity entity) 
{ 
    object originalItem; 

    EntityKey key = Context.CreateEntityKey(Context.GetEntitySet<TEntity>().Name, entity); 

    if (Context.TryGetObjectByKey(key, out originalItem)) 
    { 
     Context.ApplyCurrentValues(key.EntitySetName, entity); 
    } 
} 

Context.SaveChanges();

を呼び出すことを忘れないでください、私は自分自身がウェブ上のどこかにそれを見つけ、それを思い付くしませんでした。それは私のためにうまくいく。私はそれを組み込むためにあなたの保存方法を調整します。助けが必要なら私に知らせてください。もう少しお勧めしたいのは、disposeメソッドでObjectコンテキストをnullに設定することです。

幸運!

編集:もう一度やり直してください...管理者用コントローラのコンストラクタに基づいて、リポジトリのプライベート変数がありますか?

private IGameRepository _gameRepository; 

public AdminController(IArticleRepository articleRepository, IGameRepository gameRepository, INewsRepository newsRepository) 
    { 
     _articleRepository = articleRepository; 
     _gameRepository = gameRepository; 
     _newsRepository = newsRepository; 

コントローラはninjectによって作成されていますか?バインディングのリストにAdminControllerが表示されません。いずれのコンストラクタでも[Inject]属性が表示されません。スタックに投稿したとき、またはスタックしていないときにそれを省略しましたか?

私の他の考えは、あなたのコンテキストのInSingletonScope()が適切な答えかもしれないというアプリケーションでメモリの問題(リーク)がない場合です。

すべての質問を申し訳ありませんが、私は問題をよりよく理解しようとしています。

+0

私は私の開発マシンにアクセスできるようになった今、後でスタックトレースを投稿します。私がテストすると、InSingletonScope()を使ってObjectContextを注入すると、それが '修正'され、例外なくエンティティを更新できます。私の唯一の関心事は、キャッシュ/スレッディングです。私は、PHPの背景から来ているので、どのようにスレッドが動作するかについては完全にはわかりません。 –

+0

それは意味をなさないでしょう。 (InSingletonScope())は、編集内容を投稿した後にコメントを追加するだけです。 – bytebender

+0

スタックトレースを追加しました –

0

私自身の静的マッパーが完璧に動作します:

として呼び出されます
public static class GameMapper 
{ 
    public static Game MapFromEditModelToGame(IGameRepository repo, AdminGameViewModel formData, Game newGame) 
    { 
     newGame.GameID = formData.GameID; 
     newGame.GameTitle = formData.GameTitle; 
     newGame.GenreID = formData.GenreID; 
     newGame.LastModified = DateTime.Now; 
     newGame.ReviewScore = (short)formData.ReviewScore; 
     newGame.ReviewText = formData.ReviewText; 
     newGame.Cons = String.Join("|", formData.Cons); 
     newGame.Pros = String.Join("|", formData.Pros); 
     newGame.Slug = formData.Slug; 

     if (newGame.Platforms != null && newGame.Platforms.Count > 0) 
     { 
      var oldPlats = newGame.Platforms.ToArray(); 

      foreach (var oldPlat in oldPlats) 
      { 
       newGame.Platforms.Remove(oldPlat); 
      } 
     } 

     foreach (var platId in formData.PlatformIDs) 
     { 
      var plat = repo.GetPlatform(platId); 
      newGame.Platforms.Add(plat); 
     } 

     return newGame; 
    } 
} 

game = GameMapper.MapFromEditModelToGame(_gameRepository, formData, game); 

は私のAutoMapperマップの定義で上記の比較:

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)); 

唯一の本当の違いは私です引数としてレポを渡します。

他のすべてのコード - 私のコントローラ、私のDIなど - はまったく同じです。 の違いは、私自身のクルージングマッパーを使用しています。理想的な状況ではなく、何か。

1

IDisposableが正しく実装されていないことがわかります。あなたの処分に関連する例外の理由となりうるMaybee?

関連する問題