使用内存 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 中的单选按钮组

使用实体框架/休眠与 sql2008 地理数据类型

SQL Lite和mysql是否一样

我可以在模拟器上使用 SQL lite 和内容提供程序尝试我的 Android 测试代码吗?

sql 清洁产品magento lite #magento #clean #products

SQL LITE安装