ASP.Net vNext DbContext Dependency Injection - multiple requests.

I am trying to use ASP.Net vNext, MVC, EF7 and the repository pattern (no problem here, I don't think) ...

The problem that I am facing is that when several queries are performed against the database, I get the following error: "There is already an open DataReader associated with this Command, which must be closed first."

Here is the code:

public class Startup { public IConfiguration Configuration { get; set; } public Startup(IHostingEnvironment env) { Configuration = new Configuration().AddJsonFile("config.json").AddEnvironmentVariables(); } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Register Entity Framework services.AddEntityFramework(Configuration) .AddSqlServer() .AddDbContext<MyDbContext>(); services.AddSingleton<ILocationRepo, LocationRepo>(); services.AddSingleton<IStateRepo, StateRepo>(); } public void Configure(IApplicationBuilder app) { app.UseMvc(); var testData = ActivatorUtilities.CreateInstance<TestData>(app.ApplicationServices); testData.InitializeData(); } } 

Controller:

 [Route("api/[controller]")] public class LocationsController : Controller { private readonly ILocationRepo _repo; public LocationsController(ILocationRepo repo) { _repo = repo; } // GET: api/locations [HttpGet] public List<Location> Get() { return _repo.All.ToList(); } // GET api/locations/5 [HttpGet("{id}")] public IActionResult Get(int id) { var ret = _repo.GetById(id); if (ret == null) return new HttpNotFoundResult(); return new ObjectResult(ret); } // POST api/locations [HttpPost] public IActionResult Post([FromBody]Locationvalue) { var ret = _repo.AddOrUpdate(value); if (ret == null) return new BadRequestResult(); return new ObjectResult(ret); } // PUT api/locations/5 [HttpPut("{id}")] public IActionResult Put(int id, [FromBody]Location value) { var ret = _repo.AddOrUpdate(value); if (id == 0 || ret == null) return new BadRequestResult(); return new ObjectResult(ret); } // DELETE api/locations/5 [HttpDelete("{id}")] public IActionResult Delete(int id) { var existing = _repo.GetById(id); if (existing == null) return new HttpNotFoundResult(); bool ret = _repo.TryDelete(id); return new ObjectResult(ret); } } 

States repository:

 public class StateRepo : IStateRepo { private readonly MyDbContext context; public StateRepo(MyDbContext diContext) { context = diContext; } public IEnumerable<State> All { get { return context.States; } } public State GetById(int id) { return context.States.FirstOrDefault(x => x.Id == id); } } 

I have almost the same repo setting for locations (with several other methods, of course) ... the problem occurs when I make simultaneous AJAX calls in my locations and controller states. I would expect DI to handle such collisions for context, but it doesn't seem to be that way. Is there any other way to set this up to work correctly without going back to the old way of instantiating my context in all my repositories? Is something wrong with me?

0
source share
1 answer

I'm not claiming to be a DI expert, but try registering your repositories with AddScoped instead of AddSingleton. I think that you get the same instance of the repository for each request, which probably has the same instance of your DbContext and DbContext, is not thread safe.

Also, ensure that your connection string has MultipleActiveResultSets = true. I think this may also cause the error you see.

+5
source

All Articles