我最近开始使用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查询很好,那么问题是什么呢?
答案 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);