简体   繁体   中英

In-memory SQLite and database disappearing

I am using Nancy to create an api to a database, and am wanting to test / develop against an in-memory database.

I am using an instance of my database class in a custom bootstrapper class with the connection string Data Source=:memory: , which in turn is creating the necessary tables - I have stepped through this and I'm confident this is occuring.

I am then obtaining a new connection using the same connection string to load/save data, but even a simple select is coming up with the sql error that the table doesn't exist.

Is there a fault in this logic of creating and using a new connection with the same connection string?

You need to keep the SQLiteConnection open and ensure that the DbContext does not own the connection. This way, when the DbContext is disposed by the container, the connection doesn't get closed with it. Note: This only works with EF6. You can still pass the flag in EF5, but the context will still close the connection when the context gets disposed.

I created a TestBootstrapper which inherited the working Bootstrapper from the web project.

As part of the ConfigureRequestContainer method, I used a method factory on the DbContext registration which created a new DbContext each time, but used the existing connection. If you don't do this, the DbContext will get disposed after your first request and the second request will fail.

public class TestBootstrapper : Bootstrapper
{
    private const string ConnectionString = "data source=:memory:;cache=shared;";
    private static SQLiteConnection _connection;
    private static TestInitializer _initializer = new TestInitializer();

    protected override void ConfigureRequestContainer(TinyIoCContainer, NancyContext context) 
    {
        container.Register<Context>((_,__) => 
        {
            if (_connection == null)
                _connection = new SQLiteConnection(ConnectionString);

            // The false flag tells the context it does not own the connection, i.e. it cannot close it. (EF6 behaviour only)
            var dbContext = new Context(_connection, _initializer, false);

            if (_connection.State == ConnectionState.Closed)
                _connection.Open();

            // I build the DB and seed it here
            _initializer.InitializeDatabase(context);

            return dbContext;
        });

        // Additional type registrations
    }

    // Call this method on a [TearDown]
    public static void Cleanup() 
    {
        if (_connection != null && _connection.State == ConnectionState.Open)
            _connection.Close();
        _connection = null;
    }
}

OK, so straight from the docs:

The database ceases to exist as soon as the database connection is closed. "

However, this can be worked around with multiple connections by using cache=shared in your connection string.

However, this isn't a solution to the problem because as soon as the last connection closes, the database ceases to exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM