内存数据库不保存数据
我有一个简单的web应用程序,在客户端有角度,在服务器端有asp.net核心web-api。 我使用InMemoryDatabase
services.AddDbContext(options => options.UseInMemoryDatabase("ItemsDB"));
存储数据以简化开发。 但我遇到了一个问题。 我在web-api上有一个控制器来响应用户的请求:
[Route("api/[controller]")] public class ItemsController : Controller { private readonly IApiService apiService; public ItemsController(IApiService apiService)//using DI from Startup.cs { this.apiService = apiService; } [HttpPost, Route("addItem")] public async Task Add([FromBody]Item item) { return await apiService.Add(item); } [HttpDelete("{id}")] public async Task Delete(int id) { return await apiService.Delete(id); } [HttpPut] public async Task Put([FromBody]Item item) { return await apiService.Put(item); } }
以及以下Startup.cs配置:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext(options => options.UseInMemoryDatabase("ItemsDB")); services.AddSingleton(provider => { var context = services.BuildServiceProvider().GetService(); return new UnitOfWork(context); }); services.AddSingleton(provider => { return new ApiService(services); }); }
问题是,当我添加新项目时,一切都很好……但是我发布了另一个删除此项目的请求,它可能会显示没有这样的项目或有时可能会删除它…所以换句话说,数据库存在然后消失,我不知道什么时候。 这是一些参考上面的附加代码
public class ApiService: IApiService { private readonly IUnitOfWork database; private readonly IServiceProvider provider; public ApiService(IServiceCollection serviceCollection) { provider = serviceCollection.BuildServiceProvider(); } public IUnitOfWork Database { get { return provider.GetService(); } } public async Task Add(Item item) { Database.Items.Add(item); await Database.SaveAsync(); var id = Database.Items.LastItem().Id; return new Response() { Result = true, ItemId = id }; } public async Task Delete(int id) { var item = await db.Items.Find(id); Database.Items.Remove(item); await Database.SaveAsync(); return new Response() { Result = true }; } public async Task Put(Item item) { Database.Items.Update(item); await Database.SaveAsync(); return new Response() { Result = true }; } }
更新:UnitOfWork实施:
public class UnitOfWork: IUnitOfWork { private readonly DbContext context; private IRepository itemsRepository; public UnitOfWork(DbContext dbContext) { context = dbContext; } public IRepository Items { get { return itemsRepository ?? (itemsRepository = new Repository(context)); } } public void Dispose() { context.Dispose(); } public void Save() { context.SaveChanges(); } public async Task SaveAsync() { await context.SaveChangesAsync(); } }
你的代码有很多严重的问题,让我们来看看。
-
services.AddDbContext
添加了一个Scoped服务,这意味着将在每个请求上创建和处理实例。services.AddSingleton
添加了一个Singleton服务,因此只会创建一个实例。 您不能将作用域服务添加到单例服务,因为单例服务使用的引用将被处置,您将最终得到已处置的上下文。 -
这段代码:
return provider.GetService
(); 表示服务定位器反模式。 你可以猜到,反模式是你想要避免的。 我也不知道为什么你会想要一个服务来构建整个DI容器,也不知道为什么你希望服务有责任获得它自己需要的依赖。
-
这部分是您的问题实际来自的地方:
Database.SaveAsync();
您正在调用异步函数,而不是
await
它完成。 任务可能完成与否,它可能会抛出错误,你永远不会知道发生了什么。
最好的办法是,如果人们停止尝试在另一个工作单元和存储库上创建工作单元+存储库模式,那么所有这些都可以避免。 entity framework核心已经实现了这些:
DbContext => Unit of Work DbSet => Repository (generic)
你为什么还想要另一种抽象? 您是否真的会从项目中丢弃EF Core来certificate代码的维护成本?
整个问题代码可能是这样的:
[Route("api/[controller]")] public class ItemsController : Controller { private readonly YourContext _context; public ItemsController(YourContext context) { _context = context; } [HttpPost] public async Task Add([FromBody]Item item) { context.Items.Add(item); await context.SaveChangesAsync(); return Ok(item.Id); } [HttpDelete("{id}")] public async Task Delete(int id) { context.Items.Remove(item); await context.SaveChangesAsync(); return Ok(); } [HttpPut] public async Task Put([FromBody]Item item) { context.Items.Update(item); await context.SaveChangesAsync(); return Ok(); } }