NHibernate 与 C#-Sqlite 在 > .NET 2.0 中没有 DbConnection

Posted

技术标签:

【中文标题】NHibernate 与 C#-Sqlite 在 > .NET 2.0 中没有 DbConnection【英文标题】:NHibernate with C#-Sqlite has no DbConnection in > .NET 2.0 【发布时间】:2010-08-12 11:30:41 【问题描述】:

我尝试使用 C# Sqlite 运行我的单元测试,而不是使用此博客文章作为指导,而不是使用真正的数据库或模拟我们的数据库层:Nhibernate C# Sqlite。

不幸的是,NHibernate 要求连接是 C#-Sqlite 驱动程序未提供的 DbConnection。我查看了源代码并注意到以下代码:

#if NET_2_0
public class SqliteConnection : DbConnection, ICloneable
#else
    public class SqliteConnection : IDbConnection, ICloneable
#endif

显然,作者决定停止使用“旧”基类并改用 IDbConnection、IDbTransaction 等接口。

更改代码是没有选择的,因为这等于编写一个必须测试和维护的新客户端。

有谁知道让当前版本的 c#sqlite 与 NHibernate 一起工作的简单解决方案?

【问题讨论】:

我不确定问题到底出在哪里。我可以告诉你我是如何使用 sqlite 进行测试的...... 异常是:15:03:28,877 错误 [7] SchemaValidator [(null)]- 无法获取数据库元数据 System.InvalidCastException: Das Objekt des Typs "Community.CsharpSqlite.SQLiteClient.SqliteConnection" kann nicht 在 Typ “System.Data.Common.DbConnection” umgewandelt werden。北NHibernate.Tool.hbm2ddl.ManagedProviderConnectionHelper.Prepare() 北NHibernate.Tool.hbm2ddl.SchemaValidator.Validate() 我是移植 C#SQLite 的人。我没有意识到任何人仍然需要 NET 2.0 支持,因为所有论坛 cmets 都鼓励放弃它。此外,在大多数情况下,客户端是由 Mono 项目组提供的。如果您确实需要 Net 2.0 定义编译器选项 NET_2_0,如果这不起作用,请在 groups.google.com/group/csharp-sqlite 上开始讨论或在此处请求 csharpsqlite.uservoice.com/forums/41270-general 您尝试过连接提供商吗?成功了吗? 至少它一开始并没有让我崩溃。明天我会尝试使用会话工厂并报告;) 【参考方案1】:

我正在使用 sqlite 进行测试。我有不同的方法。

我让 NH 创建连接,但将其存储在静态变量中以将其传递给后续会话。

当我开始写测试框架的时候,我有这样的初始化代码:

static IDbConnection staticSqliteConnection;

if (staticSqlliteConnection == null)

  sessionFactory.CreateSession().Connection;

然后我遇到了一些问题,并且我的生产代码中有太多的测试特定代码(我宁愿没有)。如果您将连接传递给会话,Hi-Lo id 生成器也不起作用。

然后我写了一个 ConnectionProvider 类,如下所示:

public class SingleConnectionProvider : DriverConnectionProvider

    private static IDbConnection staticConnection = null;

    public static void ResetConnection()
    
        if (staticConnection == null) return;
        staticConnection.Dispose();
        staticConnection = null;
    

    public override IDbConnection GetConnection()
    
        if (staticConnection == null) 
        
            staticConnection = base.GetConnection();
        
        if (staticConnection.State != ConnectionState.Open)
        
            staticConnection.Open();
        
        return staticConnection;
    

    protected override void Dispose(bool isDisposing)
    
        ResetConnection();
    

在单元测试清理方法中,您调用SingleConnectionProvider.ResetConnection() 会破坏数据库以进行下一次测试。

整个事情当然不是完全线程安全的。您可以根据需要创建任意数量的会话,但应避免同时创建它们。

【讨论】:

感谢您的解决方案,我将尝试自己实现连接提供程序来解决问题。目前我只是一个测试创建一个新的会话工厂来测试 Sqlite 是如何工作的。 “Fluently.Configure()....BuildSessionFactory()” 抛出上述错误消息。从长远来看,我想用基于 sqlite 数据库的真实工厂替换所有模拟会话工厂。【参考方案2】:

如果您查看您的代码示例,

#if NET_2_0
public class SqliteConnection : DbConnection, ICloneable
#else
    public class SqliteConnection : IDbConnection, ICloneable
#endif

您可以看到,通过定义编译器选项NET_2_0,并重新编译,它将暴露旧接口

【讨论】:

啊 - 我认为 NET_2_0 是一个“内置”选项,如“调试”,并试图构建面向 .net 2.0 的项目,但没有成功。我会在星期一试试这个。感谢您移植 SQLite! 无法使用 NET_2_0 进行编译 :( DbConnectionFactory 现在被标记为“内部” - 代码无法编译。即使我将目标框架更改为 2.0。我会尽快尝试 Stefan Steineggers 的回答我手头有一些时间。【参考方案3】:

我使用 System.Data.SQLite 和自定义连接提供程序解决了这个问题:

public class SqLiteInMemoryConnectionProvider : DriverConnectionProvider

    public static IDbConnection Connection;

    public static event EventHandler ConnectionReset;

    public static void ResetConnection()
    
        if(Connection == null) return;

        Connection.Close();
        Connection.Open();

        if(ConnectionReset != null) ConnectionReset(null, new EventArgs());
    

    public override IDbConnection GetConnection()
    
        if (Connection == null)
        
            Connection = base.GetConnection();
        
        if (Connection.State != ConnectionState.Open)
        
            Connection.Open();
        
        return Connection;
    

    public override void CloseConnection(IDbConnection conn)  

与 Stefan Steineggers 解决方案的不同之处在于我正在关闭并重新打开会话以重置,因为如果我刚刚处理 NHibernate 就无法获取新连接。 此外,我在工厂类中添加了一个事件来重建会话工厂(将我们的模式导出到数据库)

SqLiteInMemoryConnectionProvider.ConnectionReset += (s, _) => RebuildSessionFactory();

【讨论】:

以上是关于NHibernate 与 C#-Sqlite 在 > .NET 2.0 中没有 DbConnection的主要内容,如果未能解决你的问题,请参考以下文章

在SQLite上使用NHibernate时获取“Dababase被锁定”(没有事务的多进程)

Fluent NHibernate and Mysql,SQLite

NHibernate、SQLite 和 Cyrillic 字符:区分大小写和回退查询

使用 SQLite“没有这样的表”测试 NHibernate - 生成模式

在我的 NHibernate / SQLite 项目中提交非常慢

通过(Fluent)NHibernate添加到SQLite DB时,DateTime不正确