带有 EF Core 和内存数据库提供程序的原始 sql
Posted
技术标签:
【中文标题】带有 EF Core 和内存数据库提供程序的原始 sql【英文标题】:Raw sql with EF Core and in-memory db provider 【发布时间】:2018-02-15 08:42:23 【问题描述】:我的一个 API 路由使用原始 sql merge into
命令来执行原子 upsert 操作,在我的自动化测试中,我有一个使用内存数据库提供程序的 TestServer
实例。它给了我一个错误,可能是因为内存提供程序不支持运行原始 sql 命令 - 这是真的吗?如果没有,我该如何让它工作?
这是用于测试的 Startup
类:
// In memory DB for testing
services.AddDbContext<MyContext>(optionsBuilder => optionsBuilder.UseInMemoryDatabase("stuff"));
services.AddDbContext<MyStatusContext>(optionsBuilder => optionsBuilder.UseInMemoryDatabase("status"));
services.AddDbContext<MyUserRolesContext>(optionsBuilder => optionsBuilder.UseInMemoryDatabase("userroles"));
API 代码如你所愿:
var count = await context.Database.ExecuteSqlCommandAsync(@"merge into ...", default(CancellationToken), ...);
return count;
此代码在生产环境中针对真实数据库运行良好,但在我的测试中,我无法让它与内存提供程序一起工作。我还有希望吗?自定义sql脚本常用的测试策略是什么?
【问题讨论】:
另外,值得注意的是,这 3 个上下文都指向同一个真实数据库,我们只是在代码中为不同的域(表集)设置了单独的上下文。 【参考方案1】:您没有希望,因为 InMemory 提供程序是 NoSQL 非关系提供程序。您应该使用 SQL Server(例如 localdb)进行集成测试
【讨论】:
是的,我有一种感觉,只是想确定一下。我们最终只是通过单元测试来解决这个问题并手动验证实际查询,这足以满足我们的需求。 @ErikEJ 你知道情况是否仍然如此吗?我正在尝试使用内存数据库上下文对FromSql
进行测试并遇到了这个问题。那里有一些嘲笑 FromSql 和 DbQuery/DbSet 的人的样本,我只是认为这不是一个好方法。
是的,这里没有任何变化
如果您在 linux 上运行 ci/cd,那么祝您使用 localdb 好运。不支持。一场经典的 M$ 灾难。那我们用什么?
SQL Express 应该符合要求【参考方案2】:
正如您发现的那样,内存中的提供程序不能进行关系操作(一个合理的限制)。
我遇到了类似的问题,最后我整理了一个库来扩展内存中的提供程序以支持关系操作 - EntityFrameworkCore.Testing。它将执行 ExecuteSqlCommand/ExecuteSqlCommandAsync 模拟。
【讨论】:
【参考方案3】:您可以使用 SQLite 代替 InMemory DB,它与 sql 配合得很好,而且设置起来非常简单,就像在内存数据库中一样。
https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/sqlite
【讨论】:
如果你打算走这条路,你不妨得到一个 Docker 容器并运行你将要使用的实际 RDBMS。不像 SQL 提供者都是可以互换的以上是关于带有 EF Core 和内存数据库提供程序的原始 sql的主要内容,如果未能解决你的问题,请参考以下文章
带有 EF Core 和 CosmosDB .NET 5 的 ASP.Net Core - IdentityRole 问题
带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何