在 .net 核心 web api 中获取 DbContext 的 Dispose 异常

问题描述 投票:0回答:1

我是 c# 和 .net core 的新手

我在 .NET 核心 web api 3.1 和 EntityFramework 上做一个项目

我有一个存储库包并应用通用存储库模式。在这个包中,我有 IRepository 接口:

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

然后我有实现该接口的 Repository 类:

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

之后,我有一个特定的模型回购类

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

这个类将来会有自己的方法。在那里我只应用了一个单例模式。

Startup类中的ConfigureService方法是这样的:

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

控制器类

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

问题是,每当我执行 POST 或 GET 请求时,我都会收到 ObjectDisposedException: SCREENSHOT

c# .net asp.net-core-webapi dbcontext
1个回答
0
投票

我有一个存储库包并应用通用存储库模式。

那是你的问题。我希望人们不要再将 Entity Framework 包装在一个严重的存储库模式中。

您将功能隐藏在一个自定义的、未记录的包装器后面,除了您之外没有人理解,它不提供任何附加功能,不提供实体框架所做的许多事情(

IEnumerable<T> GetObjectList()
不支持分页、排序或过滤例如,一旦你构建除了具有十条记录的 TODO 应用程序之外的任何东西,它就会崩溃)和实体框架的
DbSet<T>
已经是一个存储库模式。

为什么你突然在你的控制器中创建交易?存储库不应该抽象出数据库访问吗?

所以你的解决方案是删除

IRepository

Repository
并在你需要的地方注入你的
ClothingContext
,你就完成了。

如果您坚持误入歧途的存储库模式方法,那么您的其他问题是由于希望将存储库作为一种单例提供而引起的。这保留了您的 DI 框架已经处理的 DbContext。

删除单例代码。

© www.soinside.com 2019 - 2024. All rights reserved.