为什么NHibernate在HQL中简单选择到SQLite数据库不起作用?

时间:2009-08-11 06:05:06

标签: nhibernate sqlite hql

我最近开始使用FluenNHibernate,当我尝试用SQLite编写单元测试时出现了一些奇怪的问题。

我在内存数据库中使用SQLite进行测试,对于每个测试方法我都在清除数据库中存在的数据。例如:

var u = new User() { Name = "Piotr" };
_session.Save(u);
_session.Clear();
var list = _session.CreateCriteria<User>().List();

这段代码工作正常,但是当我写下一行时:

var list2 = _session.CreateQuery("FROM User").List();

我明白了:

System.Data.SQLite.SQLiteException: SQLite error
no such table: users

由NHibernate生成的sql查询很好,那么问题是什么呢?

3 个答案:

答案 0 :(得分:2)

您提到您正在使用内存中的SQLite数据库。 NHibernate可能决定在两个语句之间关闭数据库连接,这会导致丢失所有表。

防止这种情况的一种方法是创建一个自定义IConnectionProvider实现,允许您显式控制何时关闭连接。

以下是我在项目中处理此问题的原因:

public class InMemoryConnectionProvider : IConnectionProvider
{
    private static readonly object syncObject = new object();
    private static SQLiteConnection connection;

    #region IConnectionProvider Members

    public void Configure(IDictionary<string, string> settings)
    {
    }

    public void CloseConnection(IDbConnection conn)
    {
    }

    public IDbConnection GetConnection()
    {
        CreateConnection();
        if (connection.State != ConnectionState.Open)
        {
            connection.Open();
        }
        return connection;
    }

    public IDriver Driver
    {
        get { return new SQLite20Driver(); }
    }

    public void Dispose()
    {
    }

    #endregion

    public static void CreateConnection()
    {
        lock (syncObject)
        {
            if (connection == null)
            {
                var builder = new SQLiteConnectionStringBuilder
                                {
                                    DataSource = ":memory:",
                                    BinaryGUID = true,
                                    DateTimeFormat = SQLiteDateFormats.ISO8601
                                };
                connection = new SQLiteConnection(builder.ConnectionString);
                connection.Open();
            }
        }
    }

    public static void DestroyConnection()
    {
        lock (syncObject)
        {
            if (connection != null)
            {
                connection.Dispose();
                connection = null;
            }
        }
    }
}

您还需要在配置文件中设置connection.provider选项以指向此类。

在测试中,您可以在测试开始时或在设置方法中调用静态InMemoryConnectionProvider.CreateConnection()方法。完成后,您可以致电InMemoryConnectionProvider.DestroyConnection()关闭连接。由于IConnectionProvider.CloseConnection()的实现是无操作的,NHibernate将无法自行关闭连接。

答案 1 :(得分:0)

名字复数可能吗?用户 - 用户。

答案 2 :(得分:0)

我在使用内存数据库时遇到过SQLite问题。连接/会话关闭时,数据库将被销毁。使用文件变体似乎更好。

此外,必须创建数据库实体作为会话工厂设置的一部分。尝试类似会话工厂设置中的内容:

        // Create schema.
        new SchemaExport(config).Create(false, true);