使用异步存储库模式 - 无法访问已处置的对象
Using async Repository pattern - Cannot access a disposed object
我正在尝试实施异步存储库模式并希望异步更新:
我的控制器看起来像这样:
// PUT api/category
[HttpPut]
public void Put([FromBody] CategoryDto categoryDto)
{
var category = _mapper.Map<Categories>(categoryDto);
_categoryService.UpdateCategory(category);
}
我的RepositotyBase<T>
class:
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;
}
}
但是,RepositoryBase<T>
的方法 public virtual async Task Update(T entity)
的异步实现抛出错误:
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.
更新:
异步实现是否正确?
我的控制器:
// 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;
}
}
您需要设置控制器操作 PUT api/category
才能 async/await 感知。
@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://docs.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);
}
}
我正在尝试实施异步存储库模式并希望异步更新:
我的控制器看起来像这样:
// PUT api/category
[HttpPut]
public void Put([FromBody] CategoryDto categoryDto)
{
var category = _mapper.Map<Categories>(categoryDto);
_categoryService.UpdateCategory(category);
}
我的RepositotyBase<T>
class:
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;
}
}
但是,RepositoryBase<T>
的方法 public virtual async Task Update(T entity)
的异步实现抛出错误:
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.
更新: 异步实现是否正确?
我的控制器:
// 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;
}
}
您需要设置控制器操作 PUT api/category
才能 async/await 感知。
@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://docs.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);
}
}