【问题标题】:SQLite database verification after nhibernate schema generation休眠模式生成后的 SQLite 数据库验证
【发布时间】:2010-05-10 16:26:56
【问题描述】:

在使用 NHib 的模式生成工具后,验证您的 SQLite 数据库是否确实存在的最简单最有效的方法是什么?

干杯,
浆果

编辑

我希望有一些与 ISession 相关的东西(比如连接属性)可以测试;有时,在运行一系列测试时,它看起来像是一个很好的会话(IsOpen 和 IsConnected 都是真的),但是数据库不存在(针对它的查询会出现类似“没有这样的表”的错误)。

编辑 - 我现在在做什么

连接字符串和其他 cfg 属性

public static Configuration GetSQLiteConfig()
    {
        return new Configuration()
            .SetProperty(ENV.Dialect, typeof (SQLiteDialect).AssemblyQualifiedName)
            .SetProperty(ENV.ConnectionDriver, typeof (SQLite20Driver).AssemblyQualifiedName)
            .SetProperty(ENV.ConnectionString, "Data Source=:memory:;Version=3;New=True;Pooling=True;Max Pool Size=1")
            .SetProperty(ENV.ProxyFactoryFactoryClass, typeof (ProxyFactoryFactory).AssemblyQualifiedName)
            .SetProperty(ENV.ReleaseConnections, "on_close")
            .SetProperty(ENV.CurrentSessionContextClass, typeof (ThreadStaticSessionContext).AssemblyQualifiedName);
    }

我现在如何测试数据库,因为缺少“更好”的东西(这会测试映射)

        public static void VerifyAllMappings(ISessionFactory sessionFactory, ISession session)
    {
        Check.RequireNotNull<ISessionFactory>(sessionFactory);
        Check.Require(session.IsOpen && session.IsConnected);

        _verifyMappings(sessionFactory, session);
    }

    private static void _verifyMappings(ISessionFactory sessionFactory, ISession session) {
        try {
            foreach (var entry in sessionFactory.GetAllClassMetadata())
            {
                session.CreateCriteria(entry.Value.GetMappedClass(EntityMode.Poco))
                    .SetMaxResults(0).List();
            }
        }
        catch (Exception ex) {
            Console.WriteLine(ex);
            throw;
        }
    }

        public static void VerifyAllMappings(ISessionFactory sessionFactory, ISession session)
    {
        Check.Require(!sessionFactory.IsClosed);
        Check.Require(session.IsOpen && session.IsConnected);

        try {
            foreach (var entry in sessionFactory.GetAllClassMetadata())
            {
                session.CreateCriteria(entry.Value.GetMappedClass(EntityMode.Poco))
                    .SetMaxResults(0).List();
            }
        }
        catch (Exception ex) {
            Debug.WriteLine(ex);
            throw;
        }
    }

每当打开新会话时,我都会在会话提供程序中生成架构:

        public ISession Session
    {
        get
        {
            var session = (ISession)CallContext.GetData(_lookupSessionKey);
            try
            {
                if (session == null)
                {
                    _log.Debug("Opening new Session for this context.");

                    session = FactoryContext.Factory.OpenSession();

                    if(RunTypeBehaviorQualifier != RunType.Production)
                        SchemaManager.GenerateNewDb(FactoryContext.Cfg, session.Connection);
                    CallContext.SetData(_lookupSessionKey, session);
                }
            }
            catch (HibernateException ex)
            {
                throw new InfrastructureException(ex);
            }
            return session;
        }
    }

现在这一切可能都过度设计了,但我需要多个数据库连接,而且我在保持它更简单和工作时遇到了麻烦。对于一个问题,这也是很多信息,但也许其他人实际上已经将这一切归结为一门科学。下面的测试在它自己的测试夹具中运行良好,但不能与其他测试结合使用。

    [Test]
    public void Schema_CanGenerateNewDbWithSchemaApplied()
    {
        DbMappingTestHelpers.VerifyAllMappings(_dbContext.FactoryContext.Factory, _dbContext.Session);
    }

【问题讨论】:

    标签: unit-testing nhibernate sqlite


    【解决方案1】:

    绿柱石,

    据我所知,您正在与映射实体作斗争,因为您使用的是不同的连接。是否有任何要求要求您使用多个“真实”数据库连接?我的意思是,您的测试可以共享同一个会话(逻辑上)吗?如果没有,您可以简单地将数据库配置为:

          <property name="connection.connection_string">Data Source=NonTransactionalDB.txt;Version=3;New=True;Pooling=True;Max Pool Size=1;</property>
    

    其中重要的部分是池化选项。由于每个会话都将使用相同的连接,因此每次都重新创建架构不会有问题。

    但请务必记住,它向您介绍了有关交易的一些限制。 As SQLite can't handle more than one transaction per connection,并行运行测试会给您带来问题(类似于“数据库文件被锁定”异常”)。

    干杯,

    菲利普

    【讨论】:

    • YES - 这解决了我的单元测试问题!不,我认为,就需要多个“真实”连接而言(尚不确定“真实”是什么意思)。我需要桌面应用程序中两个数据库的两个并发连接。虽然我确实需要交易,所以即使我的一些交易测试似乎有效,“NonTransactionalDB.txt”听起来也不好。如果我需要或最终需要多个“真实”连接怎么办?干杯
    • @jfries - 哦,是的,你有什么技巧可以测试 SQLite 数据库是否可用?干杯
    • @Berryl:NonTransactionalDB.txt 是一个不好的例子。它与一些 NH 配置类的内部单元测试有关。但是,由于 SQLite 每个连接不能处理多个事务,是的,您不能同时打开两个不同的事务(它会引发锁定的数据库异常)。我将使用此信息更新我的答案。
    • @Berryl:我们只是在配置数据库后测试它是否配置正确。我们通过检查 Configuration.Properties 和 Configuration.GetClassMapping 来做到这一点。
    • @jFries:我现在正在对它运行查询,如果没有数据库,这显然会失败,我希望有 / 可以更方便地测试数据库是否可用。不确定验证 cfg 输入是否意味着您有一个工作数据库,但也许我错过了它。你能告诉我你的代码吗?干杯
    【解决方案2】:

    Berryl,只是为了更容易想象,我将发布另一个答案。如果对您有帮助,请随时给我另一个。 :)

    下面是我用来检查我的 NH 配置对象是否配置正确的代码。

            // assert: verify some properties just to see if connection properties were applyed ane entities mapped
            Assert.AreEqual<string>(cfg.Properties["connection.connection_string"], @"Server=localhost;Initial Catalog=MoveFrameworkDataNHibernate;User Id=sa;Password=sa");
            Assert.AreEqual<string>(cfg.Properties["dialect"], "NHibernate.Dialect.MsSql2000Dialect");
            Assert.IsNotNull(cfg.GetClassMapping(typeof(MappedEntity)));
    

    真诚地,我并不觉得可以使用 DB 检查配置对象,但这是一种知道的方式:是的,我的实体在那里并且我指向正确的 DB。

    我了解您害怕使用第二个 SQLite 连接,并且数据库在前一个连接中暴露,因此您会遇到不希望的异常,但据我所知,检查您的实体是否是唯一的另一个选项会有类似下面的代码。但是,由于它指的是 SessionFactory,所以它只提供了前一个选项。

            tx.Session.SessionFactory.GetClassMetadata(typeof(MappedEntity)) != null
    

    在这种情况下,我能想到的最后一个选项是通过 EXISTS 检查直接对您的数据库执行 SQL。我不知道 EXISTS 命令在所有 DB 实现之间有多不可知,但对于我们在这里讨论的简单检查来说,这应该不是什么大问题。

    希望这会有所帮助!

    顺便说一句:这是 jfneis。尼斯是一个姓氏。与薯条、炸薯条或类似的东西无关。 :)

    干杯。

    菲利普

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      • 2015-06-08
      • 2017-08-22
      • 2018-05-01
      • 2018-06-27
      相关资源
      最近更新 更多