为什么HQL到SQLite数据库中的NHibernate simple select不起作用?

为什么HQL到SQLite数据库中的NHibernate simple select不起作用?,nhibernate,sqlite,hql,Nhibernate,Sqlite,Hql,我最近开始使用FluenHibernate,当我试图用SQLite编写单元测试时,出现了一些奇怪的问题 我使用SQLite内存数据库进行测试,对于每个测试方法,我都会清除数据库中存在的数据。例如: var u = new User() { Name = "Piotr" }; _session.Save(u); _session.Clear(); var list = _session.CreateCriteria<User>().List(); 我得到: System.Data.S

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

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

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

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

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

可能是名称多元化?用户-用户。

您提到您正在使用内存中的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;
            }
        }
    }
}
MemoryConnectionProvider中的公共类:IConnectionProvider { 私有静态只读对象syncObject=新对象(); 私有静态SQLiteConnection; #区域IConnectionProvider成员 公共无效配置(IDictionary设置) { } 公共连接(IDbConnection conn) { } 公共IDbConnection GetConnection() { CreateConnection(); if(connection.State!=ConnectionState.Open) { connection.Open(); } 回路连接; } 公共驾驶员 { 获取{返回新的SQLite20Driver();} } 公共空间处置() { } #端区 公共静态void CreateConnection() { 锁定(同步对象) { if(连接==null) { var builder=new-SQLiteConnectionStringBuilder { DataSource=“:内存:”, BinaryGUID=true, DateTimeFormat=SQLiteDateFormats.ISO8601 }; 连接=新的SQLiteConnection(builder.ConnectionString); connection.Open(); } } } 公共静态连接() { 锁定(同步对象) { if(连接!=null) { connection.Dispose(); 连接=空; } } } } 您还需要在配置文件中设置
connection.provider
选项以指向此类


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

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

此外,数据库实体必须作为会话工厂设置的一部分创建。在会话工厂设置中尝试以下操作:

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

在再次获取列表之前,您可以尝试刷新会话。很抱歉,没有看到错误。可能会混淆数据库表名User和映射中给出的名称。您必须使用映射中的名称,而不是表名。第二个查询真的是代码中的下一行吗?您确定第二个查询不在另一个会话上吗?因此,为了澄清,如果我随意启动和处理ISession,那么数据库肯定不会跨ISession存在?如果是这样,它将解释为什么在创建任何ISession之前,当我尝试将架构推送到内存中的数据库时,会得到“没有这样的表”,或者,如果我在*.hbm.xml文件中指定架构,“未知数据库”。这可能是“没有这样的表”错误的原因。不过,“未知数据库”听起来像是别的东西。SQLite不支持模式,但我认为NHibernate的当前版本通过使用下划线而不是点来伪造它(即,“schema_table”而不是“schema.table”)。如果您使用的是旧版本,或者没有配置SQLite方言,那么它可能会尝试使用点,SQLite将其解释为试图通过ATTACH database语句访问另一个附加的数据库(我假设您没有这样做)。
        // Create schema.
        new SchemaExport(config).Create(false, true);