Attach in-memory sqlite database to physical database connection in c#

98 views Asked by At

I have a physical sqlite database on disk and a named in-memory database that I need to run joint queries against. Reading the documentation, it's not quite clear if this is possible or how to accomplish this.

Looking at the documentation on https://www.sqlite.org/inmemorydb.html I see the phrase "When an in-memory database is named in this way, it will only share its cache with another connection that uses exactly the same name."

That phrase "exactly the same name" leads me to think this isn't possible.

var dbFile = @"D:\Downloads\test.db3";
if (File.Exists(dbFile))
    File.Delete(dbFile);

// create connection to physical db
var physicalCon = new SqliteConnection(new SqliteConnectionStringBuilder
{
    DataSource = dbFile,
    Mode = SqliteOpenMode.ReadWriteCreate,
    Cache = SqliteCacheMode.Shared,
    Pooling = false
}.ToString());
physicalCon.Open();

// create connection to in-memory db
var memoryCon = new SqliteConnection(new SqliteConnectionStringBuilder
{
    DataSource = "memtest",
    Mode = SqliteOpenMode.Memory,
    Cache = SqliteCacheMode.Shared,
    Pooling = false
}.ToString());
memoryCon.Open();

try
{
    // create some tables in physical db, insert values, and test read
    using (var p1Cmd = physicalCon.CreateCommand())
    {
        p1Cmd.CommandText = "CREATE TABLE Phys (Val TEXT);";
        p1Cmd.ExecuteNonQuery();
        p1Cmd.CommandText = "INSERT INTO Phys (Val) Values ('Phys1'), ('Phys2');";
        p1Cmd.ExecuteNonQuery();
        p1Cmd.CommandText = "SELECT * FROM Phys;";
        using var pReader = p1Cmd.ExecuteReader();
        while (pReader.Read())
        {
            Debug.WriteLine("P : " + pReader.GetString(0));
        }
    }

    // create some tables in memory db, insert values, and test read
    using (var m1Cmd = memoryCon.CreateCommand())
    {
        m1Cmd.CommandText = "CREATE TABLE Mem (Val TEXT);";
        m1Cmd.ExecuteNonQuery();
        m1Cmd.CommandText = "INSERT INTO Mem (Val) Values ('Mem1'), ('Mem2');";
        m1Cmd.ExecuteNonQuery();
        m1Cmd.CommandText = "SELECT * FROM Mem;";
        using var mReader = m1Cmd.ExecuteReader();
        while (mReader.Read())
        {
            Debug.WriteLine("M : " + mReader.GetString(0));
        }
    }

    // attach memory db to physical db connection
    using (var attach = physicalCon.CreateCommand())
    {
        attach.CommandText = "ATTACH DATABASE 'file:memtest?mode=memory&cache=shared' AS m;";
        attach.ExecuteNonQuery();
    }

    // read memory db values from physical db connection
    using (var testCmd = physicalCon.CreateCommand())
    {
        testCmd.CommandText = "SELECT * FROM m.Mem;"; // exception 'm.Mem' table does not exist
        using var reader = testCmd.ExecuteReader();
        while (reader.Read())
        {
            Debug.WriteLine("T : " + reader.GetString(0));
        }
    }
}
finally
{
    physicalCon.Close();
    memoryCon.Close();
}
0

There are 0 answers