Adam Pope
Adam Pope

Reputation: 3274

Testing NHibernate with SQLite "No Such Table" - schema is generated

I'm trying to use an in-memory SQLite database to test my data layer which is provided by NHibernate.

I've read a load of blogs and articles about getting this setup but I'm now very confused as to why it isn't working.

The problem - when I run a unit test I get the error 'no such table: Student'. The articles I've read suggest this is because the schema isn't getting generated, or, the connection is being closed between my SchemaExport and query. I've checked everywhere I can think of and can't see how either of these scenarios are occuring.

My test output log looks like this:

OPEN CONNECTION

drop table if exists "Student"

drop table if exists "Tutor"

create table "Student" (
    ID  integer,
   Name TEXT,
   DoB DATETIME,
   TutorId INTEGER,
   primary key (ID)
)

create table "Tutor" (
    ID  integer,
   Name TEXT,
   primary key (ID)
)
NHibernate: INSERT INTO "Student" (Name, DoB, TutorId) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 'Text1', @p1 = 01/12/2010 14:55:05, @p2 = NULL
14:55:05,750 ERROR [TestRunnerThread] AbstractBatcher [(null)]- Could not execute query: INSERT INTO "Student" (Name, DoB, TutorId) VALUES (@p0, @p1, @p2); select last_insert_rowid()
System.Data.SQLite.SQLiteException (0x80004005): SQLite error

no such table: Student

at System.Data.SQLite.SQLite3.Prepare(String strSql, SQLiteStatement previous, String& strRemain)

at System.Data.SQLite.SQLiteCommand.BuildNextCommand()

at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)

at System.Data.SQLite.SQLiteDataReader.NextResult()

at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)

at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)

at System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior behavior)

at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()

at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)

14:55:05,781 ERROR [TestRunnerThread] ADOExceptionReporter [(null)]- SQLite error
no such table: Student
DISPOSE
CLOSING CONNECTION

Originally I was using my own code for the connection/session management but have moved to the code in this blog post translated to C# and with a couple changes to the DBConfig method and some debug statements to show the state of the connection.

private FluentNHibernate.Cfg.Db.IPersistenceConfigurer GetDBConfig()
{
    return SQLiteConfiguration.Standard
                               .ConnectionString((ConnectionStringBuilder cs) => cs.Is(CONNECTION_STRING))
                               .ProxyFactoryFactory("NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu")
                               .Raw("connection.release_mode", "on_close");
}

I added the on_close after reading this

My test code looks like this:

[Test]
public void CanGetStudentById()
{
    using (var scope = new SQLiteDatabaseScope<StudentMapping>())
    {
        using (ISession sess = scope.OpenSession())
        {
            // Arrange
            var repo = new StudentRepository();
            repo.Save(new Student() { Name = "Text1", DoB = DateTime.Now });

            // Act
            var student = repo.GetById(1);

            // Assert
            Assert.IsNotNull(student);
            Assert.AreEqual("Text1", student.Name);
        }
   }
}

What have I overlooked here?

Update: I created a copy of the class that connects to an SQLite file DB and it worked fine. So it has to be something to do with the connection being closed.

Upvotes: 4

Views: 4558

Answers (1)

James Kovacs
James Kovacs

Reputation: 11661

If you change your test method to the following, does it work?

[Test]
public void CanGetStudentById()
{
    using (var scope = new SQLiteDatabaseScope<StudentMapping>())
    {
        using (ISession sess = scope.OpenSession())
        {
            // Arrange
            sess.Save(new Student() { Name = "Text1", DoB = DateTime.Now });

            // Act
            var student = sess.Get<Student>(1);

            // Assert
            Assert.IsNotNull(student);
            Assert.AreEqual("Text1", student.Name);
        }
   }
}

I would hazard to guess that your StudentRepository is opening its own session and hence doesn't see the table.

Upvotes: 3

Related Questions