0

この問題のスレッドはたくさんありますが、ほとんどの場合、ループして保存しようとする人のコンテキスト私がやっていることではないIListではなくIQueryableです。MVC Core 2.0 EFコアSqlException:セッション内で他のスレッドが実行されているため、新しいトランザクションは許可されません

コントローラとリポジトリの間でコンテキストが渡される問題が発生しています。私はこの問題を私のアプリのどこかに持っていますが、これを簡単に説明し再現する方法は以下の通りです。

まず、Startup.csで自分のDbContextをサービスとして設定します。

services.AddDbContext<ApplicationDbContext>(options => 
     options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

次に、注入されるコントローラがあります。最初の2つのセーブは、コントローラーから直接コンテキストを使用すると正常に動作しますが、レポから使用すると、タイトルの例外とともにエラーが発生します。レポに保存しようとする前にコントローラにレコードを保存するとエラーが発生するだけであることに注意してください。 、これは任意のDB書き込み用のエントリポイントである必要があり

public class InitiativeRepository 
{ 
    private ApplicationDbContext _context; 
    private ApplicationUser _user; 

    public InitiativeRepository(ApplicationDbContext context, ApplicationUser user) 
    { 
     _context = context; 
     _user = user; 
    } 

    public Initiative Get(int id, bool eagerLoad = false) 
    { 
     if (!eagerLoad) 
     { 
      return _context.Initiatives.SingleOrDefault(i => i.Id == id); 
     } 
     else 
     { 
      return _context.Initiatives.Include(i => i.Tasks).ThenInclude(t => t.ActionItems). 
       SingleOrDefault(i => i.Id == id); 
     } 
    } 

    public List<Initiative> GetAll() 
    { 
     return _context.Initiatives.ToList(); 
    } 

    public Initiative Update(Initiative Entity) 
    { 
     _context.Update(Entity); 
     _context.SaveChanges(); // This line causes the exception. 
     return Entity; 
    } 

} 

しかし、私は、ASP.NETのIDを使用していますが、このセッションのためで自動ログオンしていますので、私:ここ

private ApplicationDbContext _context; 
private UserManager<ApplicationUser> _userManager; 

private ApplicationUser _user 
    { 
     get 
     { 
      return _userManager.GetUserAsync(User).Result; 
     } 
    } 

public InitiativesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager) 
    { 
     _context = context; 
     _userManager = userManager; 
    } 

    // GET: Initiatives 
    public IActionResult Index() 
    { 

     Initiative i2 = new Initiative(); 
     i2.Id = 2; 
     i2.InitiativeName = "testname"; 
     _context.Update(i2); 
     _context.SaveChanges(); // Works fine 

     var i4 = _context.Initiatives.SingleOrDefault(init => init.Id == 2); 
     i4.InitiativeName = "blep"; 
     _context.Update(i4); 
     _context.SaveChanges(); // Works fine 


     InitiativeRepository initiativeRepository = new InitiativeRepository(_context, _user); 

     var i= initiativeRepository.Get(2); 
     i.InitiativeName = "blah"; 
     initiativeRepository.Update(i); //Throws exception 

     var initiatives = initiativeRepository.GetAll(); 
     return View(initiatives); 
    } 

は、リポジトリクラスですそれがこれにも影響を及ぼしているかどうかは分かりません。

+0

最初の2つのUpdates()が実際に何かをしていますか?私が考えることができる唯一の説明は、それらが事実上NO-OPであるということです(DB内のデータは既にあなたが設定しようとしているものなので)。しかし第3のものは実際に変更しようとしていますが、このコードの外からアクティブな結果セットが開かれているためです。 –

+0

うわー、私は文字列リテラルを変更することができ、私はDBに反映された更新を見ることができます。私は、あなたがこのコードの外で開いたアクティブな結果セットを持っているという点で正しいと思います。 VS2017を閉じてもう一度開いたところ、このコードは正常に動作しましたが、アプリのある時点で別の領域が同じエラーメッセージで爆発しました。私はそれを閉じないでいくつかの結果セットを開く必要がありますが、私はどこを把握することはできません。私はまた、なぜこれが断続的であるのか理解していません。 – tarun713

答えて

-2

代わりにsavechangesasync()メソッドを使用してみてください。

+1

これの裏づけはありますか?説明してください。 –

0

私はいつも依存性注入を信じていませんが、このようなことに起こります。それは迷惑ですが、あなたはより良いあなたのレポですべてをやったり、他の閉じを介して、あなたのコンテキストの処分のいずれか務めたことがあります。でも、それはすべきではないものの起きても何

、これは単なる推測です。それが渡されたときに注入がコンテキストの間違った状態をキャッチしているかどうかです。代わりにリポジトリのコンストラクタに依存性注入を行い、リポジトリ内で直接CRUD操作ですべてを行います。

private InitiativeRepository _initiativeRepository; 


public InitiativesController(ApplicationDbContext context, UserManager<ApplicationUser> userManager) 
{ 
    _context = context; 
    _userManager = userManager; 
    _initiativeRepository = new InitiativeRepository(_context, _user); 

} 

コントローラを搭載した.NET Core 2 Web Apiでは、上記のようなパターンになります。私は文脈を保ち、それを閉じないで、それを使用する別の状態とその文脈を混ぜ合わせるときはいつでも知っている、私は困っている。私は文脈のために依存性注入を使用しないように私に打ち明けましたので、彼らがデフォルトとしている新しい.NET Coreのもので面白いです。大規模なデータベースやマルチユーザアプリケーションが大量の作業をするまでは、おそらくうまくいくでしょう。

関連する問題