在没有本机池的情况下保持有效的DB连接活动
本文关键字:有效 DB 活动 连接 情况下 本机 | 更新日期: 2023-09-27 18:14:03
是否有任何方法可以保持数据库连接打开并准备在运行时使用?我们的WCF服务应该保持这种连接方式。现在我们有了类似于下面这段代码的代码:
// This is the class of objects that has connections within.
[DataContract]
public class SomeObj
{
[DataMember]
public string Name { get; set; }
public OracleConnection Conn { get; set; }
}
// Dictionary of SomeObjs
private static Dictionary<string, SomeObj> myObjs = new Dictionary<string, SomeObj>();
当服务启动时,它也从自己的配置文件中连接所有数据库。但正如您所知,连接可能会损坏,无法使用,甚至最终无法访问。所以为了消除这个问题,我们有一个特殊的计时器来检查config中的所有连接:
// Setup timer method. Timer will fire every minute.
static private void CreateTimer()
{
Timer Timer1 = new System.Timers.Timer();
Timer1.Enabled = true;
Timer1.Interval = 60000;
Timer1.Elapsed += new System.Timers.ElapsedEventHandler(Timer1_Elapsed);
}
static private void Timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Parallel.ForEach(Program.config.Root.Elements("databases"), el =>
{
try
{
Program.OpenConnection(el.Attribute("name").Value);
}
catch (Exception exc)
{
Console.WriteLine(DateTime.Now.ToString() + " " + exc);
}
});
// This is old way we checks connections consistently
//foreach (XElement element in Program.config.Root.Elements("databases"))
//{
// try
// {
// AServ.OpenConnection(el.Attribute("name").Value);
// }
// catch (Exception exc)
// {
// Console.WriteLine(DateTime.Now.ToString() + " " + exc);
// }
//}
}
public static bool OpenConnection(string name)
{
// if connections exactly doesn't exists
if (!myObjs.ContainsKey(name))
{
XElement el = (from t in config.Root.Elements("databases")
where t.Attribute("name").Value == name
select t).FirstOrDefault();
if (el == null)
{
lock (myObjs)
{
myObjs.Remove(name);
}
return false;
}
lock (myObjs)
{
myObjs.Add(name, new SomeObj { Conn = new OracleConnection { ConnectionString = el.Attribute("connectionString").Value } }, Name = el.Attribute("name").Value);
}
}
// if connection broken
if ((myObjs[name].Conn.State != ConnectionState.Open || !myObjs[name].Conn.Ping()) && myObjs.ContainsKey(name))
{
try
{
// Trying to get it alive
lock (myObjs)
{
myObjs[name].Conn.Close();
myObjs[name].Conn.Open();
}
}
catch (Exception e)
{
if (!myObjs.ContainsKey(name))
return false;
lock (myObjs)
{
myObjs.Remove(name);
}
return false;
}
Console.WriteLine(DateTime.Now.ToString() + " " + myObjs[name].Conn.ConnectionString);
}
return true;
}
还有一件事你应该知道,伙计们,就是我们如何在方法本身中保持连接:
private static int GetParameterValue(string name, int id)
{
// if we don't get parameter value at the moment because broken connection
if (!OpenConnection(name))
return -1;
// assuming connection is OK and getting the parameter value
string parameterQuery = @"select GetInfo(:id) from dual";
OracleCommand parameterCommand = new OracleCommand(parameterQuery, myObjs[name].Conn);
parameterCommand.Parameters.Add("id", id);
return Convert.ToInt32(parameterCommand.ExecuteScalar());
}
问题是有时第一次计时器检查不能及时完成,而第二次计时器检查在第一次运行时开始。它给出了堆内存泄漏的一些奇怪的错误(我认为是这样)。另一个问题是,即使我们开发的单例设计模式只有一个检入时间,检入可能会挂起,而另一个检入永远不会被触发(因为打开连接对某些数据库来说花费了很长过高的时间)。我不知道为什么会这样,但是我们试着加了Connection timeout=30;
,但是说实话我不记得给出了正确的结果。当然不是)。
那么这个服务运行时,它占用的内存和它运行时一样多。我用这段代码尝试了很多操作,甚至有一次在代码的某个地方遇到了死锁(几乎100%的CPU负载)。
是的,我知道本机ado.net池,但我们不能使用它,因为我们有大量的遗留代码库,以上述方式工作,应该以某种方式改进现有的检查逻辑。
那么告诉我你的想法,我们如何在没有池化的情况下及时获得连接?我需要一些方法,可以使用尽可能少的内存(现有的代码占用更多的内存,因为它运行),并与小的代码更改快速工作。
任何帮助都是非常感激的!真心希望大家对stackoverflow社区有所帮助!
我考虑使用特殊的线程,它将在最后与Thread.Sleep(60000)
循环检查连接。但我不确定。
ado.net提供程序是Devart dotConnect for Oracle。数据库为Oracle 9-11(取决于服务器),c# . net Framework 4.
- 在此注册表位置找到您的oracle主页HKLM'SOFTWARE' oracle(例如C:'oracle'client'10g) 打开ORACLE_HOME下的network'admin目录(例如C:'oracle'client'10g'network'admin)
- 打开(如果不存在,则创建)一个名为sqlnet.ora的文件
- 添加以下行:SQLNET。EXPIRE_TIME = 1
将会发生的是每1分钟向DB服务器发送一个探针,这将导致连接保持活跃。
希望有帮助。丹尼尔