ServiceStack:检测IDbConnection是否“繁忙” - 是否有DataReader处于打开状态(尝试实现“连接池”)

3
我正在测试ServiceStack的OrmLite。我之前使用过没有OrmLite的MySql,现在我面临的问题最容易用以下错误消息来描述:
“已经存在与此连接关联的打开的DataReader,必须先关闭它。”
由于我的应用程序是多线程的,某些线程将轮询数据库,而其他线程将根据需要进行插入、更新或选择操作。这导致了上述异常。
我需要做的是能够检测连接(IDbHandler)是否“忙”,是否有打开的DataReader或其他东西。如果它很忙,就使用下一个连接(从我想要实现的“连接池”中)。但问题是,我无法在IDbHandler对象中使用任何方法或属性来确定它是否忙碌。
在“普通”的mysql情况下,我通过使用一个方法来解决这个问题,其中我发送MySqlCommand或只发送查询字符串,例如:
dbConnections.ExecuteQuery("SELECT * FROM test");
dbConnections.ExecuteQuery(cmd); // cmd == MySqlCommand

ExecuteQuery方法会处理查找打开的连接并将cmd/query传递给它。但是,由于我正在使用OrmLite,它有许多扩展方法到IDbConnection,我不想为每个方法创建“代理方法”。在上面简单的mysql情况下,只需要一个方法,它接受MySqlCommand,但在OrmLite中的许多方法中并非如此。

第一个问题:

  • 如何检测连接是否繁忙?我想避免try-catch情况来检测它。

第二个问题:

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

示例:

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));

为什么不依赖于内置的连接池? - usr
那个是哪一个,我在哪里可以找到相关信息等? - Ted
我也遇到了同样的问题。 - 7wp
它是SQL Server ADO.NET类的内置功能。每个连接器都实现了自己的池。我相信MySQL/NET也具有池,因为没有池的数据库连接器处于可怕的劣势。https://www.google.com/webhp?complete=1&hl=en#complete=1&hl=en&q=mysql+net+connector+pooling(让我猜猜 - 您最初是Java或C开发人员?)。 - usr
不好意思,我几乎是纯C# =) - Ted
显示剩余3条评论
1个回答

3

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

在我的使用中,所有服务都继承我的父服务(其又继承Service),该服务处理一些常见的元数据处理。我选择让我的基础服务覆盖Service的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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接