3

我正在测试 ServiceStacks OrmLite。我以前使用过没有 OrmLite 的 MySql,现在我遇到了这个错误消息中最容易描述的问题:

已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭它。

由于我有一个多线程应用程序,某些线程将轮询数据库,而其他线程将在需要时插入、更新或选择“按需”。这导致上述异常。

我需要做的是能够检测连接(IDbHandler)是否“忙”;有一个开放的 DataReader 或其他东西。如果它很忙,请进行下一个连接(来自我要实现的“连接池”)。问题是,我无法在 IDbHandler 对象中使用任何方法或属性来确定它是否忙。

我在“正常” mysql 案例中解决了这个问题,只需使用一个方法,我发送 MySqlCommand 或仅发送查询字符串,例如:

dbConnections.ExecuteQuery("SELECT * FROM test");
dbConnections.ExecuteQuery(cmd); // cmd == MySqlCommand

并且 ExecuteQuery 将处理找到一个打开的连接并在那里传递 cmd/查询。

但是,由于我使用的是 OrmLite,它有很多 IDbConnection 的扩展方法,我不想为每个方法创建“代理方法”。在上面的简单 mysql 案例中,实际上只需要一个方法,它接受一个 MySqlCommand,但对于 OrmLite 中的许多方法则不然。

第一个问题:

  • 如何检测连接是否繁忙?我想避免尝试捕获的情况来检测它。

第二个问题:

  • 是否有某种方法可以传递整个“方法”调用,例如:

例子:

dbConnections.Run(iDbHandler.Select<MyObject>(q => q.Id > 10));
// or
dbConnections.Run(iDbHandler.Where<MyObject>(q => q.Id > 10));
// or
dbConnections.Run(iDbHandler.SomeOtherWeirdMetod<MyObject>(q => bla bla bla));
4

1 回答 1

3

到目前为止,这不是最好的解决方案,但这是我正在测试的一种方法,以查看它如何处理我的特定情况(目前在 3.97 版)。像 Ted 一样,我经常看到开放数据读取器出现异常,或者连接被返回为关闭。

在我的使用中,所有服务都继承了我的父服务(后者又继承了服务),它处理一些常见的元数据处理。我选择让我的基础服务覆盖服务的 Db 属性并快速检查 Db 连接的状态并尝试恢复。立即修复的一种情况如下:

我的 MsSql 服务器正在故障转移集群中运行。当 SQL 服务器从节点 A 翻转到节点 B 时,我在 ServiceStack 中发现没有内置机制来检测其内存中的连接是“脏的”并且需要重新连接。

欢迎提出意见和改进。

public override System.Data.IDbConnection Db
{
    get
    {
        try
        {
            var d = base.Db;
            if (d == null || d.State != System.Data.ConnectionState.Open)
                return  ForceNewDbConn();
            else
                return d;
        }
        catch (Exception ex)
        {
            return ForceNewDbConn();
            //throw;
        }
    }
}

private IDbConnection ForceNewDbConn()
{
    try
    {
        var f = TryResolve<IDbConnectionFactory>();
        if (f as OrmLiteConnectionFactory != null)
        {
            var fac = f as OrmLiteConnectionFactory;
            fac.AutoDisposeConnection = true;
            var newDBconn = fac.Open();
            return newDBconn;
        }
        return base.Db;
    }
    catch (Exception ex)
    {
        throw;
    }
}
于 2013-12-07T15:26:20.343 回答