没有这样的表-内存中带有Sqlite的EF Core

时间:2018-06-28 10:29:56

标签: c# entity-framework-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();                
        }
    }
}

2 个答案:

答案 0 :(得分:3)

要回答OP,我相信问题在于访问数据库的多个上下文,如果没有共享缓存,这将无法正常工作。将您的连接字符串更改为:"DataSource=file::memory:?cache=shared"

对于那些从Google到这里徘徊的人,还有一些其他需要牢记的事情:

  • 至少一个连接必须保持对数据库开放。
  • 如果将从多个连接访问数据库,则必须使用共享缓存,如下所示:string connectionString = "DataSource=file::memory:?cache=shared";
  • 如果使用ADO.NET,则官方提供程序不适用于Entity Framework。即使正确配置了所有内容,我在测试时也遇到“没有这样的表”错误,但是一旦从System.Data.SQLite.SQLiteConnection(System.Data.SQLite.Core nuget程序包)更改为Microsoft提供程序:{{1} },错误消失了。
  • 官方Sqlite ADO.NET适配器比Microsoft的快 2倍!因此,除非绝对必要,否则最好使用官方的Sqlite适配器。

示例代码:

Microsoft.Data.Sqlite.SqliteConnection

还请记住要read the documentation! :)

答案 1 :(得分:0)

SQLite内存数据库仅在连接打开时存在。您可以使用其他DbContext,但是如果关闭连接,则内存db将被删除。

Example