c# - 没有这样的表 - 内存中带有 Sqlite 的 EF Core
问题描述
我正在尝试设置我的测试环境,但我在使用 Sqlite 适配器时遇到了问题。每个创建的上下文都有相同的连接,因此应该为每个上下文正确构建内存数据库。
但是当我尝试添加新内容时,它会抛出错误:“没有这样的表:%here_is_my_tablename%”。
我觉得我的配置应该不错。
根据:
public abstract class BaseServiceTests : IDisposable
{
protected readonly SqliteConnection Connection;
public BaseServiceTests()
{
Connection = new SqliteConnection("DataSource=:memory:");
Connection.Open();
Assert.NotNull(Connection);
using (var ctx = BuildCoreContext())
{
ctx.Database.EnsureCreated();
}
using (var ctx = BuildWebContext())
{
ctx.Database.EnsureCreated();
}
}
public void Dispose()
{
Connection.Close();
}
public DbContextOptions<TContext> Options<TContext>() where TContext: DbContext
{
var options = new DbContextOptionsBuilder<TContext>()
.UseSqlite(Connection)
.Options;
return options;
}
public ServiceRequestCoreContext BuildCoreContext()
{
var ctx = new ServiceRequestCoreContext(Options<ServiceRequestCoreContext>(), null);
ctx.Database.OpenConnection();
return ctx;
}
public ServiceRequestWebContext BuildWebContext()
{
var ctx = new ServiceRequestWebContext(Options<ServiceRequestWebContext>(), null);
ctx.Database.OpenConnection();
return ctx;
}
}
测试
public class RequestServiceTests : BaseServiceTests
{
public async Task Prepare()
{
using (var ctx = BuildCoreContext())
{
await ctx.RequestTypes.AddAsync(new RequestType((int)RequestTypes.Order, "TestType - test"));
await ctx.RequestStatuses.AddAsync(new RequestStatus((int)RequestStatuses.AcceptedForVeryfication, "test - test", "test - test"));
await ctx.Companies.AddAsync(new CustomerCompany(1, "test - test", "Test - test"));
await ctx.SaveChangesAsync();
}
}
[Fact]
public async Task when_creating_new_request_it_should_not_be_null()
{
//Arrange
await Prepare();
var customerId = 1;
var iGen = new IdentifyGenerator();
//Act
using (var webCtx = BuildWebContext())
{
webCtx.Database.OpenConnection();
var service = new RequestService(webCtx, BuildCoreContext(), iGen);
await service.CreateAsync(customerId);
await webCtx.SaveChangesAsync();
}
//Assert
using (var ctx = BuildWebContext())
{
ctx.ServiceRequests.Should().HaveCount(1);
ctx.ServiceRequests.FirstOrDefault().Should().NotBeNull();
}
}
}
解决方案
要回答 OP,我认为问题在于访问数据库的多个上下文,如果没有共享缓存,这将无法工作。将您的连接字符串更改为:"DataSource=file::memory:?cache=shared"
。
对于那些从谷歌徘徊在这里的人,这里还有一些其他的事情要记住:
- 至少一个连接必须保持对数据库的开放。
- 如果将从多个连接访问数据库,则必须使用共享缓存,如下所示:
string connectionString = "DataSource=file::memory:?cache=shared";
- 如果使用 ADO.NET,官方提供程序无法与实体框架一起正常工作。即使我已经正确配置了所有内容,我在测试时也遇到了“没有这样的表”错误,但是一旦我从:
System.Data.SQLite.SQLiteConnection
(System.Data.SQLite.Core nuget 包)更改为 Microsoft 提供程序:Microsoft.Data.Sqlite.SqliteConnection
然后错误就消失了。 - 官方的 Sqlite ADO.NET 适配器比微软的快2 倍!因此,除非您绝对必须,否则最好使用官方的 Sqlite 适配器。
示例代码:
[Fact]
public async Task MyTest()
{
var dbContext = new MyDbContext("DataSource=file:memdb1?mode=memory&cache=shared");
try
{
await dbContext.Database.OpenConnectionAsync();
// Test your dbContext methods, which has an open connection to the in-memory database
// If using ADO.NET to make new connections, use Microsoft.Data.Sqlite.SqliteConnection
}
finally
{
await dbContext.Database.CloseConnectionAsync();
}
}
还记得阅读文档!:)
更新:为了使内存数据库的测试更容易,我创建了一个继承自我的 DbContext 的 TestContext,以便自动处理连接和数据库创建:(这次使用 NUnit)
public sealed class TestContext : UsersContext
{
public TestContext(string connectionString) : base(connectionString)
{
Database.OpenConnection();
Database.EnsureCreated();
}
public override void Dispose()
{
Database.CloseConnection();
base.Dispose();
}
}
用法:
[Test]
public void AddingUsersShouldIncrementId()
{
using (var dbContext = new TestContext("DataSource=file::memory:?cache=shared"))
{
dbContext.UsersDbSet.Add(new UserEntity());
dbContext.SaveChanges();
uint actualId = dbContext.Users.Single().Id;
Assert.AreEqual(1, actualId);
}
}
推荐阅读
- c# - 使用 UDP 广播检测网络上的多个设备 - C#
- python - 使用 Beautifulsoup 下载文件时出错
- java - 将 jpa 与 hibernate 一起使用时,找不到 hibernate.properties 和 java.lang.NoClassDefFoundError
- pandas - 在 pandas 中读取多个表并将块数据写入 postgres 数据库
- android - 背景菜单顶部的嵌套滚动视图 Material Theme Android
- asp.net-core - 如果作为 Web 应用程序部署到 IIS,则注销不起作用
- vb.net - 如何用我的程序资源中的文件覆盖特定文件夹中的文件
- excel - 基于单元格值循环遍历另一个工作簿中的范围
- onsen-ui - SortableJS 无法在桌面上使用 Onsen UI
- android - 一旦安装了带电容器的 BackgroundGeolocation 插件,就无法在 Android 上构建 Ionic App