c# - 使用异步存储库模式 - 无法访问已处置的对象

标签 c# asp.net-core async-await entity-framework-core repository-pattern

我正在尝试实现异步存储库模式并希望异步更新:

我的 Controller 如下所示:

// PUT api/category
[HttpPut]
public void Put([FromBody] CategoryDto categoryDto)
{
     var category = _mapper.Map<Categories>(categoryDto);
     _categoryService.UpdateCategory(category);
}

我的RepositotyBase<T>类:

public abstract class RepositoryBase<T> where T : class
{
    public virtual async Task Update(T entity)
    {            
        // This code throws error: Cannot access a disposed object. A common 
        // cause of this error is disposing ...
        await Task.Run(() => { // I have **await** here 
            dbSet.Attach(entity);
            shopContext.Entry(entity).State = EntityState.Modified;
        });
    }
}

我的CategoryService :

public class CategoryService : ICategoryService
{    
    public async Task UpdateCategory(Categories category)
    {
        await _categoryRepository.Update(category); // I have **await** here 
        _unitOfWork.Commit();
        return;
    }
}

但是,方法 public virtual async Task Update(T entity) 的异步实现的RepositoryBase<T>抛出错误:

public abstract class RepositoryBase<T> where T : class
{
    public virtual async Task Update(T entity)
    {            
        // This code throws error: Cannot access a disposed object. A common 
        // cause of this error is disposing ...
        await Task.Run(() => {
            dbSet.Attach(entity); // I have **await** here 
            shopContext.Entry(entity).State = EntityState.Modified;
        });
    }
}

Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

更新: 这是正确的异步实现吗?

我的 Controller :

// PUT api/category
[HttpPut]
public void Put([FromBody] CategoryDto categoryDto)
{
     var category = _mapper.Map<Categories>(categoryDto);
     _categoryService.UpdateCategory(category);
}

我的通用存储库:

public abstract class RepositoryBase<T> where T : class
{
    public virtual async Task Update(T entity)
    {            
        dbSet.Attach(entity);
        shopContext.Entry(entity).State = EntityState.Modified;
    }
}

我的工作单位:

public class UnitOfWork : IUnitOfWork
{
    private readonly IDbFactory dbFactory;
    private StoreEntities dbContext;

    public UnitOfWork(IDbFactory dbFactory)
    {
        this.dbFactory = dbFactory;
    }

    public StoreEntities DbContext
    {
        get { return dbContext ?? (dbContext = dbFactory.Init()); }
    }

    public async Task CommitAsync()
    {
        //DbContext.Commit();
        await DbContext.SaveChangesAsync();
    }
}

我的服务:

public class CategoryService : ICategoryService
{    
    public async Task UpdateCategory(Categories category)
    {
        _categoryRepository.Update(category); // I have **await** here 
        await Task.Run(()=> {_unitOfWork.Commit()}); // 
        return;
    }
}

最佳答案

您需要将 Controller 操作 PUT api/category 设置为异步/等待感知。 @mjwills 在评论中提到了这一点。

// PUT api/category
[HttpPut]
public async Task Put([FromBody] CategoryDto categoryDto)
{
     var category = _mapper.Map<Categories>(categoryDto);
     await _categoryService.UpdateCategory(category);
     // you probably want to set a response code. e.g return OK()
}

这有点离题,但我正在讨论其他一些评论。 您还需要将更改保存到 EF 中的数据库。您不需要手动创建自己的任务。据我所知,EF 为您提供了一个 SaveChangesAsync 方法:https://learn.microsoft.com/en-us/ef/core/saving/async .

public abstract class RepositoryBase<T> where T : class
{
    public virtual async Task Update(T entity)
    {            
        dbSet.Attach(entity);
        shopContext.Entry(entity).State = EntityState.Modified;
        await shopContext.SaveChangesAsync();
    }
}

public class CategoryService : ICategoryService
{    
    public async Task UpdateCategory(Categories category)
    {
        return await _categoryRepository.Update(category);
    }
}

关于c# - 使用异步存储库模式 - 无法访问已处置的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57952486/

相关文章:

c# - 使用和不使用 await 运算符的任务执行

c# - 如何确保 Task.Delay 更准确?

javascript - onkeyup 事件似乎没有触发或被忽略

c# - Web 应用程序中基于文化的 ToString() 方法

c# - 格式化 DateTime 错误 "No overload for method ' ToString' 需要 1 个参数”

dependency-injection - ASP.NET 5 依赖注入(inject) - [FromServices] 属性是否仅在 Controller 中有效?

.net - 使用带有 dotnet 核心的 MSTest、xUnit 或 NUnit

c# - ASP.NET Core MVC 应用程序请求永远不会完成

c# - MongoDB 无尽的查找 ToListAsync

c# - 隐藏 WPF 窗口直到完全加载