Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Getting Dispose exception for DbContext in .net core web api

Im new to c# and .net core

Im doing a project on .NET core web api 3.1 and EntityFramework

I have a repository package and applying Generic Repository Pattern. In this package i have IRepository Interface:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public interface IRepository<T> where T:class
{
    void InsertObject(T obj);
    void DeleteObject(int objId);
    void UpdateObject(T obj);
    T GetObjectById(int obj);
    IEnumerable<T> GetObjectList();
}

Then I have Repository class that implements that Interface:

 public class Repository<T> : IRepository<T> where T : class
{
    private readonly ClothingContext dbContext;

    public Repository(ClothingContext clothing)
    {
        dbContext = clothing;
    }
    public void Insert(int objId){
        var obj = dbContext.Set<T>().Find(objId);
        dbContext.Set<T>().Remove(obj);
        dbContext.SaveChanges();
    }

    public T GetObjectById(int obj)
    {
        return dbContext.Set<T>().Find(obj);
    }

    public IEnumerable<T> GetObjectList()
    {
        var originalObjects = dbContext.Set<T>().ToList();
        return originalObjects;
    }

    public void InsertObject(T obj)
    {
        dbContext.Set<T>().Add(obj);
        dbContext.SaveChanges();
    }

    public void UpdateObject(T obj)
    {
        dbContext.Entry(obj).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
    }

    public void DeleteObject(int objId)
    {
        var obj = dbContext.Set<T>().Find(objId);
        dbContext.Set<T>().Remove(obj);
        dbContext.SaveChanges();
    }
}

After, I have a specific model repo class

public class ProductRepository : Repository<Product>
{
    private static ProductRepository productRepository;
    public ProductRepository(ClothingContext clothingContext) : base(clothingContext)
    {
    }

    public static ProductRepository GetInstance(ClothingContext clothing)
    {
        if(productRepository == null)
        {
            productRepository = new ProductRepository(clothing);
        }
        return productRepository;
    }
}

This class will in future have its own methods. In there I only applying a singleton pattern.

ConfigureService method in Startup class is like this:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ClothingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ClothingApp11270")));
        services.AddControllers();
        services.AddTransient<IRepository<Product>, ProductRepository>();
    }

Controller class

[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    private readonly ProductRepository productRepository;

    public ProductController(ClothingContext clothingContext)
    {
        productRepository = ProductRepository.GetInstance(clothingContext);
    }
    // GET: api/<ProductController>
    [HttpGet]
    public IActionResult Get()
    {
        return new OkObjectResult(productRepository.GetObjectList());
    }

    // GET api/<ProductController>/5
    [HttpGet("{id}" ,Name ="GetProductById")]
    public IActionResult Get(int id)
    {
        return new OkObjectResult(productRepository.GetObjectById(id));
    }

    // POST api/<ProductController>/a
    [HttpPost]
    public IActionResult Post([FromBody] Product product)
    {
        using(var scope = new TransactionScope())
        {
            productRepository.InsertObject(product);
            scope.Complete();
            return CreatedAtAction(nameof(Get), new { ID = product.Id }, product);
        }
    }

    // PUT api/<ProductController>/5
    [HttpPut]
    public IActionResult Put([FromBody] Product product)
    {
        if(product != null)
        {
            using (var scope = new TransactionScope())
            {
                productRepository.UpdateObject(product);
                scope.Complete();
                return new OkResult();
            }
        }
        return new NoContentResult();
    }

    // DELETE api/<ProductController>/5
    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        productRepository.DeleteObject(id);
        return new OkResult();
    }
}

The problem is, whenever I doing a POST or GET request I get ObjectDisposedException: SCREENSHOT

>Solution :

I have a repository package and applying Generic Repository Pattern.

Well that’s your problem right there. I wish people would stop wrapping Entity Framework in a crippling repository pattern.

You’re hiding functionality behind a custom, undocumented wrapper that nobody except you understands, that does not offer any additional functionality, that does not offer many of the stuff that Entity Framework does (IEnumerable<T> GetObjectList() does not support paging nor sorting nor filtering for example and will break as soon as you build anything other than a TODO app with like ten records) and Entity Framework’s DbSet<T> ALREADY IS a repository pattern.

And why are you suddenly creating transactions within your controller? Shouldn’t the repository abstract the database access away?

So your solution would be to remove IRepository and Repository and just inject your ClothingContext where you need it, and you’re done.

If you insist on the misguided repository pattern approach, your additional problem is caused by wanting to provide the repository as a kind-of-singleton. This holds on to a DbContext that your DI framework has already disposed.

Remove the singleton code.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading