Тайм-аут SQL Server в рекурсивном коде

У меня есть базовый класс, который реализует мое подключение к базе данных. У меня есть второй класс, который наследует этот базовый класс базы данных. Второй класс имеет некоторую рекурсию внутри него, где при оценке его значения он может создать экземпляр другого экземпляра второго класса. Рекурсия лишь на несколько уровней. Я запускаю все однопоточное.

Мой код будет работать правильно в течение 1 или 2 минут, затем я начинаю получать согласованные ошибки: «Истекло время ожидания». Период ожидания истекает до получения соединения из пула ».

У моего базового класса есть деструктор, который вызывает метод .Dispose () для объектов базы данных. Мой второй класс имеет деструктор, который закрывает объект соединения в базовом классе.

Моя строка подключения к базе данных указывает время ожидания соединения = 0.

Любые идеи относительно того, почему код будет работать корректно в течение нескольких минут, а затем начнет отсчет времени, пытаясь подключиться к базе данных? Я озадачен.

namespace BaseLib2 { public class TSBase { protected StreamWriter logFile; protected OleDbCommand queryCmd; protected OleDbCommand exeCmd; protected OleDbConnection connection; protected OleDbDataReader reader; public SqlConnection sqlconn;//used for BCP public TSBase() { } ~TSBase() { try { queryCmd.Dispose(); exeCmd.Dispose(); reader.Dispose(); connection.Dispose(); sqlconn.Dispose(); } catch (Exception ex) { Console.WriteLine("BaseLib2 destrutor:" + ex.Message); } } public void ConnectToDB() { string connString = "Provider=SQLNCLI11;Server=myserver;Database=mydb;Uid=myid;pwd=password;connection timeout=0"; queryCmd = new OleDbCommand(); exeCmd = new OleDbCommand(); connection = new OleDbConnection(connString); queryCmd.CommandTimeout = 60000; exeCmd.CommandTimeout = 60000; connection.Open(); queryCmd.Connection = connection; exeCmd.Connection = connection; string sqlConnString = "server=dc2k8housql;database=mydb;Uid=myid;pwd=password;connection timeout=0"; sqlconn = new SqlConnection(sqlConnString); sqlconn.Open(); } 

 public class Expression : BaseLib2.TSBase { private string ExpName; private string ExpressionTxt; private string sql; private DateTime Contract_dt; private DateTime Quote_dt; private bool SaveToDB; private string BaseSymbol; public Expression(string expNameIn, DateTime contract_dtIn, DateTime quote_dtIn) { ExpName = expNameIn; Contract_dt = contract_dtIn; Quote_dt = quote_dtIn; try { try { ConnectToDB(); } catch (Exception ex) { Console.WriteLine("Error in EXP constructor connecting to database." + ex.Message ); throw new Exception("Error in EXP constructor connecting to database."); } //get expression text from database sql = "select expression, save_to_db, coalesce(base_symbol, '') as base_symbol from expressions where exp_name = " + DBI(ExpName); reader = ReadData(sql); if (reader.Read())//should only return 1 row { ExpressionTxt = reader[0].ToString(); SaveToDB = bool.Parse(reader[1].ToString()); BaseSymbol = reader[2].ToString(); } reader.Close(); } catch (Exception ex) { Console.WriteLine("Exception in Expression constructor:" + ex.Message); } } ~Expression() { try { connection.Close(); sqlconn.Close(); connection.Dispose(); sqlconn.Dispose(); } catch (Exception ex) { Console.WriteLine("Error in destructor:" + ex.Message); } } public double Eval() { try { //check to see if there are any $RV in the expression if (ExpressionTxt.Contains("$RV(")) { //parse and evaluate the $RV's String[] split = ExpressionTxt.Split(("$".ToCharArray())); foreach (string s in split){ Console.WriteLine("s=" + s); if (s.Length > 3)//make sure we have a string with a symbol in it { //for each rv we find, create a new expression and evaluate it if (s.Substring(0, 3).Contains("RV")) { int pStart = s.IndexOf("("); int pEnd = s.IndexOf(")"); string rvSymb = s.Substring(pStart + 1, pEnd - pStart - 1); System.Console.WriteLine(rvSymb); Expression oExp = new Expression(rvSymb, Contract_dt, Quote_dt); double rVal = oExp.Eval();//recursive call oExp = null; ExpressionTxt = ExpressionTxt.Replace("$RV(" + rvSymb + ")", rVal.ToString()); } } } } //replace SV values in formula if (ExpressionTxt.Contains("$SV(")) { //find symbols in $SV brackets and collect contract dates String[] split = ExpressionTxt.Split (("$".ToCharArray())); foreach (string s in split) { if (s.Length > 3) {//make sure we have a symbol if (s.Substring(0, 3).Contains("SV")) { int pStart = s.IndexOf("("); int pEnd = s.IndexOf(")"); string svSymb = s.Substring(pStart + 1, pEnd - pStart - 1); System.Console.WriteLine("sv=" + svSymb); //replace $SV with numerical values double sVal = GetQuoteValue(svSymb); ExpressionTxt = ExpressionTxt.Replace("$SV(" + svSymb + ")", sVal.ToString()); } } } } //evaluate double ret = Evaluate(ExpressionTxt); Console.WriteLine(ExpName + "=" + ret.ToString()); if (SaveToDB) { Console.WriteLine(ExpName + " cd:" + Contract_dt.ToShortDateString() + " qd:" + Quote_dt.ToShortDateString() + ": saving to db..."); sql = "delete from exp_quotes where exp_name = " + DBI(ExpName ) ; sql = sql + " and contract_dt = " + DBI(Contract_dt.ToShortDateString()); sql = sql + " and quote_dt = " + DBI(Quote_dt.ToShortDateString()); WriteData(sql); sql = "insert into exp_quotes(exp_name, contract_dt, quote_dt, calculated_dt, price) values("; sql = sql + DBI(ExpName ) + "," + DBI(Contract_dt.ToShortDateString()) + "," + DBI(Quote_dt.ToShortDateString()); sql = sql + ", getdate(), " + ret + ")"; WriteData(sql); } connection.Close();//after we evaluate, close down the connection connection.Dispose(); return ret; //return value } catch (Exception ex) { Console.WriteLine("exp:" + ExpName + " cd:" + Contract_dt.ToShortDateString() + " qd:" + Quote_dt.ToShortDateString() + " = " + ex.Message); } return 0; } private double GetQuoteValue(string symbIn) { double ret = 0; sql = "select close_val from prices_union_all_vw where symbol = " + DBI(symbIn) + " and contract_dt = " + DBI(Contract_dt.ToShortDateString()) + " and quote_dt = " + DBI(Quote_dt.ToShortDateString()); reader = ReadData(sql); if (reader.Read()) { ret = Double.Parse(reader[0].ToString()); reader.Close(); } else {//we didn't get a record for the specific quote date, try again using the mostrecent view sql = "select close_val from prices_union_all_mostrecent_vw where symbol = " + DBI(symbIn) + " and contract_dt = " + DBI(Contract_dt.ToShortDateString()); reader = ReadData(sql); if (reader.Read()) { ret = Double.Parse(reader[0].ToString()); } reader.Close(); } return ret; } private static double Evaluate(string expression) { var loDataTable = new DataTable(); var loDataColumn = new DataColumn("Eval", typeof(double), expression); loDataTable.Columns.Add(loDataColumn); loDataTable.Rows.Add(0); return (double)(loDataTable.Rows[0]["Eval"]); } 

Вы исчерпываете свой доступный пул соединений, потому что вы создаете соединение с базой данных для каждого выражения и подвыражения, которое вы анализируете, и они не очищаются вовремя, чтобы повторно использоваться.

Решение. Не делайте соединения рекурсивно, или итеративно, или что-то еще. Сделайте один для одной цели и просто используйте его. И если вам нужно освободить время подключения для повторного использования, не полагайтесь на деструкторы класса, потому что они не запускаются, когда вы хотите их использовать.

В общем, классы, которые неявно выделяют ограниченные внешние ресурсы (например, соединения) в своих Инициализаторах, должны быть довольно статическими объектами, и вы, естественно, обычно не хотите наследовать их в классе, который предназначен для создания объектов так же динамически, как и для синтаксического анализатора.

Вы пробовали продлить период ожидания? Добавьте большой тайм-аут в строку подключения, например «Время ожидания подключения = 1800». Обычно это помогает мне, когда я получаю такие сообщения.

Другое дело, что вы можете увидеть, если вы можете улучшить запрос больше.

Вы можете проверить настройку соединения Max для базы данных. Также проверьте, сколько активных подключений открыто, когда новые попытки подключения начинают тайм-аут.

Как определить общее количество открытых / активных подключений в ms sql server 2005

Interesting Posts
Давайте будем гением компьютера.