内存数据库不保存数据 [英] In-memory database doesn't save data

查看:58
本文介绍了内存数据库不保存数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的Web应用程序,在客户端具有angular的功能,在服务器端具有asp.net核心的Web-api.我使用InMemoryDatabase

I have a simple web-app with angular on client-side and asp.net core web-api on server-side. I use InMemoryDatabase

services.AddDbContext<ItemsContext>(options => options.UseInMemoryDatabase("ItemsDB"));

存储数据以简化开发.但是我遇到了一个问题.我在web-api上有一个控制器来响应用户的请求:

to store data for the simplisity of the development. But I've encountered an issue with that. I have one controller on web-api to response for users' requests:

[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<Response> Add([FromBody]Item item)
    {
        return await apiService.Add(item);
    }

    [HttpDelete("{id}")]
    public async Task<Response> Delete(int id)
    {
        return await apiService.Delete(id);
    }

    [HttpPut]
    public async Task<Response> Put([FromBody]Item item)
    {
         return await apiService.Put(item);
    }
}

以及以下Startup.cs配置:

and the following Startup.cs configurations:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddDbContext<ItemsContext>(options => options.UseInMemoryDatabase("ItemsDB"));
    services.AddSingleton<IUnitOfWork, UnitOfWork>(provider => {
        var context = services.BuildServiceProvider().GetService<ItemsContext>();
        return new UnitOfWork(context);
    });
    services.AddSingleton<IApiService, ApiService>(provider => {
        return new ApiService(services);
    });
}

问题是,当我添加新项目时,一切都很好...但是随后我发布了另一个删除该项目的请求,这可能表明根本没有这样的项目,或者有时它可能删除了它. ..so换句话说,数据库存在,然后消失,我不确定何时.这是引用上述

The problem is, that when I add new item, everything goes just fine...but then I post another request to delete this item it may show there there is no such an item at all or sometimes it may delete it...so in other words, the database exists and then disappears and I'm not sure when. Here is some additional code refering to the above

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

    public async Task<Response> 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<Response> 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<Response> Put(Item item)
    {
        Database.Items.Update(item);
        await Database.SaveAsync();
        return new Response() { Result = true };
    }
}

更新: UnitOfWork实施:

Update: UnitOfWork Implementation:

 public class UnitOfWork: IUnitOfWork
{
    private readonly DbContext context;
    private IRepository<Item> itemsRepository;

    public UnitOfWork(DbContext dbContext)
    {
        context = dbContext;
    }

    public IRepository<Item> Items
    {
        get
        {
            return itemsRepository ?? (itemsRepository = new Repository<Item>(context));
        }
    }

    public void Dispose()
    {
        context.Dispose();
    }

    public void Save()
    {
        context.SaveChanges();
    }

    public async Task SaveAsync()
    {
        await context.SaveChangesAsync();
    }
}

推荐答案

您的代码有多个严重问题,让我们解决它们.

Your code has multiple serious problems, let's go through them.

  1. services.AddDbContext添加了一个范围服务,这意味着将在每个请求上创建并处理实例. services.AddSingleton添加了Singleton服务,因此将仅创建一个实例.您无法将范围服务添加到单项服务中,因为单项服务使用的引用将被处置,并且最终将获得处置上下文.
  2. 此代码:

  1. services.AddDbContext adds a Scoped service, meaning that instances will be created and disposed on each request. services.AddSingleton adds a Singleton service, so only a single instance will ever be created. You cannot add a scoped service to a singleton one, because the reference the singleton service uses will be disposed and you will end up with a disposed context.
  2. This code:

return provider.GetService<IUnitOfWork>();

代表服务定位器反模式.如您所料,您想避免使用反模式.我也不知道为什么为什么您希望服务构建整个DI容器,或者为什么您不希望服务负责获取其自身所需的依赖关系.

represents the service locator anti-pattern. As you can guess, an anti-pattern is something you want to avoid. I also don't know why you would want a service to build the entire DI container nor why you would want a service to have the responsibility of getting the dependencies it needs itself.

这部分实际上是您的问题出处:

This part here is where your question actually comes from:

Database.SaveAsync();

您正在调用异步函数,而不是await使其无法完成.任务可能完成或未完成,可能会引发错误,您将永远不知道发生了什么.

You are calling an asynchronous function and not awaiting for it to finish. The task may finish or not, it may throw an error or not, you will never know what happened.

最好的事情是,如果人们停止尝试在另一个工作单元和存储库上创建工作单元+存储库模式,则可以避免所有这些情况.实体框架核心已经实现了这些:

The best thing is that all of these could be avoided if people stopped attempting to create a Unit of Work + Repository pattern over yet another Unit of Work and Repository. Entity Framework Core already implements these:

DbContext => Unit of Work
DbSet => Repository (generic)

为什么还要另一个抽象?您真的会从项目中舍弃EF Core来证明代码的维护成本合理吗?

Why do you want yet another abstraction? Will you really ever throw away EF Core from the project to justify the maintenance cost of your code?

整个问题代码可能就是这样:

The entire question code could have just been this:

[Route("api/[controller]")]
public class ItemsController : Controller
{
    private readonly YourContext _context;

    public ItemsController(YourContext context)
    {
       _context = context;
    }

    [HttpPost]
    public async Task<IActionResult> Add([FromBody]Item item)
    {
        context.Items.Add(item);
        await context.SaveChangesAsync();

        return Ok(item.Id);
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(int id)
    {
        context.Items.Remove(item);
        await context.SaveChangesAsync();

        return Ok();
    }

    [HttpPut]
    public async Task<IActionResult> Put([FromBody]Item item)
    {
        context.Items.Update(item);
        await context.SaveChangesAsync();

        return Ok();
    }
}

这篇关于内存数据库不保存数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆