使用内存 sql lite 对流利的 nhibernate 存储库进行单元测试 - 没有这样的表错误
Posted
技术标签:
【中文标题】使用内存 sql lite 对流利的 nhibernate 存储库进行单元测试 - 没有这样的表错误【英文标题】:Unit test fluent nhibernate repository with in memory sql lite - no such table error 【发布时间】:2013-05-10 10:51:32 【问题描述】:我正在尝试使用 Fluent NHibernate 为存储库模式编写单元测试。 我选择使用内存中的 sqlite 数据库以避免 sql server 访问(这可以用于集成测试)。
这是我使用的类:
public enum ExpenseCategory
Eat,
Clothes,
Car,
Leisure,
Rent,
House,
Lecture,
Trip,
Restaurent
public class Expense
public virtual int Id get; set;
public virtual ExpenseCategory Category get; set;
public virtual double Amount get; set;
public virtual bool IsNecessary get; set;
public virtual bool IsPeriodic get; set;
public virtual string Comment get; set;
public ExpenseMapping()
Table("Expense");
Id(x => x.Id).Column("idexpense");
Map(x => x.Category).Column("category");
Map(x => x.Amount).Column("amount");
Map(x => x.IsNecessary).Column("isnecessary");
Map(x => x.IsPeriodic).Column("isperiodic");
Map(x => x.Comment).Column("comment");
interface IRepository<T>
T GetById(int id);
void SaveOrUpdate(T entity);
void Delete(T entity);
List<T> GetAll();
public interface IDatabase
Configuration Config get; set;
ISessionFactory Session get; set;
public class NhibernateRepository<T> : IRepository<T>
private readonly Configuration _configuration;
private readonly ISessionFactory _session;
public NhibernateRepository(IDatabase database)
_configuration = database.Config;
_session = database.Session;
public T GetById(int id)
T retrievedObject;
using (var session = _session.OpenSession())
using (var transaction = session.BeginTransaction())
retrievedObject = session.Get<T>(id);
transaction.Commit();
return retrievedObject;
public void SaveOrUpdate(T entity)
using (var session = _session.OpenSession())
using (var transaction = session.BeginTransaction())
session.SaveOrUpdate(entity);
transaction.Commit();
public void Delete(T entity)
using (var session = _session.OpenSession())
using (var transaction = session.BeginTransaction())
session.Delete(entity);
transaction.Commit();
public List<T> GetAll()
IList<T> allObjects;
using (var session = _session.OpenSession())
using (var transaction = session.BeginTransaction())
allObjects = session.CreateCriteria(typeof (T)).List<T>();
transaction.Commit();
return (List<T>)allObjects;
public class DatabaseSqlLite : IDatabase, IDisposable
public Configuration Config get; set;
public ISessionFactory Session get; set;
public DatabaseSqlLite()
Session = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory().ShowSql())
.Mappings(m => m.FluentMappings
.Add(typeof(ExpenseMapping))
)
.ExposeConfiguration(x => Config = x)
.BuildSessionFactory();
SchemaExport export = new SchemaExport(Config);
export.Execute(true, true, false, Session.OpenSession().Connection, null);
public void Dispose()
//S.Dispose();
public class DatabaseSqlServer : IDatabase
public Configuration Config get; set;
public ISessionFactory Session get; set;
public DatabaseSqlServer()
Config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(m => m.Server(@".\SqlExpress")
.Database("databasename")
.TrustedConnection()))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
.BuildConfiguration();
Session = Config.BuildSessionFactory();
使用控制台应用程序中的 DatabaseSqlServer 类可以得到正确的结果。 尝试使用 DatabaseSqlLite 类进行单元测试会给我错误:
public class RespositoryTest
[Fact]
public void InsertAndLoadExpense()
var database = new DatabaseSqlLite();
var repository = new NhibernateRepository<Expense>(database);
var expense = new Expense()
Amount = 3,
IsNecessary = true,
IsPeriodic = true,
Category = ExpenseCategory.Car
;
repository.SaveOrUpdate(expense);
Assert.Equal(1, repository.GetAll().Count);
错误:
PRAGMA foreign_keys = OFF
drop table if exists Expense
PRAGMA foreign_keys = ON
create table Expense (
idexpense integer primary key autoincrement,
category TEXT,
amount DOUBLE,
isnecessary BOOL,
isperiodic BOOL,
comment TEXT
)
NHibernate:INSERT INTO Expense(类别、金额、必要、 等周期,评论)值(@p0,@p1,@p2,@p3,@p4);选择 last_insert_rowid();@p0 = 'Car' [类型:字符串 (0)],@p1 = 3 [类型: Double (0)],@p2 = True [类型:布尔 (0)],@p3 = True [类型:布尔 (0)], @p4 = NULL [类型:字符串 (0)]
NHibernate.Exceptions.GenericADOException 无法插入: [MoneyManagerCore.Expense][SQL: INSERT INTO Expense(类别、金额、 isnecessary, isperiodic, comment) VALUES (?, ?, ?, ?, ?);选择 last_insert_rowid()] à NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)à NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] 字段,布尔 [] notNull,SqlCommandInfo sql,对象 obj, ISessionImplementor 会话)à NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] 字段、对象 obj、ISessionImplementor 会话)à NHibernate.Action.EntityIdentityInsertAction.Execute() à NHibernate.Engine.ActionQueue.Execute(IExecutable 可执行文件)à NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(对象 实体,EntityKey 键,IEntityPersister 持久化器,布尔值 useIdentityColumn,对象任何东西,IEventSource 源,布尔值 需要ImmediateIdAccess) à NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(对象 实体、对象 id、IEntityPersister 持久化器、布尔值 useIdentityColumn,对象任何东西,IEventSource 源,布尔值 需要ImmediateIdAccess) à NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(对象 实体,字符串 entityName,对象任何东西,IEventSource 源, Boolean requiresImmediateIdAccess) à NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent 事件)à NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent 事件)à NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent 事件)à NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent 事件)à NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent 事件) à NHibernate.Impl.SessionImpl.SaveOrUpdate(Object obj) à MoneyManagerRepository.NhibernateRepository`1.SaveOrUpdate(T entity) dans NhibernateRepository.cs:第 56 行 UnitTests.RespositoryTest.InsertAndLoadExpense() dans RespositoryTest.cs:第 28 行 System.Data.SQLite.SQLiteException SQL 逻辑错误或缺少数据库没有这样的表:费用
谁能帮我解决这个问题?
【问题讨论】:
我应该在打开会话时保持“使用语法”还是应该只在开始时打开会话?我都试过了,但仍然有同样的错误。 拜托,谁能帮我解决这个问题?谢谢!! 【参考方案1】:发生的情况是您打开一个连接,创建表并丢弃连接,然后打开另一个指向空数据库的连接。
使用 sqlite inmemory 连接必须始终相同,因为 inmemory 数据库随着连接而生死。
我愿意:
-
将
public ISessionFactory Session get; set;
设为私有并将其重命名为 sessionfactory,因为 Session 具有误导性
有一个方法public ISession OpenSession()
并在SqlLiteDatabase 中实现它return _sessionfactory.OpenSession(_connection);
其中连接与SchemaExport().Execute
中使用的连接相同
【讨论】:
以上是关于使用内存 sql lite 对流利的 nhibernate 存储库进行单元测试 - 没有这样的表错误的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SQL-lite 数据库检索到 android studio 中的单选按钮组
我可以在模拟器上使用 SQL lite 和内容提供程序尝试我的 Android 测试代码吗?