#c# #asp.net #sql #sql-server-2008 #iis-7
#c# #asp.net #sql #sql-server-2008 #iis-7
Вопрос:
Я использую ASP.NET Framework 4, IIS 7 и SQL Server 2008 R2.
Я получил ошибку типа: {column} not found in selected DataSource,
, ….
SQL Reader is close
Это происходит только тогда, когда:
- Подключено несколько пользователей.
- Они выполняют вызовы CRUD (создание, повторный поиск, обновление, удаление) одновременно.
Как ни странно, это ускользает от моего улова:
try{
Connexion_D.GetConnected();
// doing CRUD
}
catch{
// catching Error, avoid yellow page aspx
}
finally
{
Connexion_D.CloseConnection();
}
И мой класс подключения:
public class Connexion_D
{
static public SqlConnection conn;
static public SqlConnection GetConnected()
{
try
{
String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
conn = new SqlConnection(strConnectionString);
}
catch (Exception excThrown)
{
conn = null;
throw new Exception(excThrown.InnerException.Message, excThrown);
}
// Ouverture et restitution de la connexion en cours
if (conn.State == ConnectionState.Closed) conn.Open();
return conn;
}
static public Boolean IsConnected
{
get { return (conn != null) amp;amp; (conn.State != ConnectionState.Closed) amp;amp; (conn.State != ConnectionState.Broken); }
}
static public void CloseConnection()
{
// Libération de la connexion si elle existe
if (IsConnected) conn.Close();
}
}
Поэтому я не думаю, что код неправильный / содержит ошибку.
Я думаю, что это может быть конфигурация IIS и SQL server.
Есть идеи?
Заранее благодарю.
Комментарии:
1. Пожалуйста, укажите полную информацию об ошибке и пример кода, который продемонстрирует ошибку, т.Е. достаточно информации для повторного создания. Также читайте tinyurl.com/so-hints для получения дополнительных советов о том, как сделать этот вопрос ответственным.
2. В выбранном источнике данных не найдено поле или свойство с именем ‘XXX’. но, как я уже сказал, это происходит только при многопользовательском использовании, потому что я проверил, что этот xxx существует, и у меня нет проблем, когда я подключаюсь один.
3. Для ExecuteReader требуется открытое и доступное соединение. В данный момент соединение закрыто.
Ответ №1:
Если я правильно понимаю, что вы делаете, то это выглядит очень сомнительно:
static public SqlConnection conn;
static public SqlConnection GetConnected() {
try
{
String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
conn = new SqlConnection(strConnectionString);
}
}
static public void CloseConnection() {
// Libération de la connexion si elle existe
if (IsConnected) conn.Close();
}
Вы работаете со статической переменной соединения, что означает, что когда вы закрываете ее, вы закрываете последнюю, которая была открыта.
В многопользовательском сценарии это может произойти:
- Пользователь A: Создайте соединение (и верните соединение 1)
- Пользователь A: Выполнить запрос (выполняется с подключением 1)
- Пользователь B: Создайте соединение (и верните соединение 2)
- Пользователь A: Закрыть соединение (последним открытым было 2, так что оно закрыто)
- Пользователь B: Выполнить запрос (выполняется для подключения 2, оно уже закрыто … взрыв)
Кроме того, вам, вероятно, следует пересмотреть использование вашего соединения в качестве общедоступной переменной-члена:
static public SqlConnection conn;
Обычно это считается плохой практикой и может привести к неожиданным / трудноотслеживаемым ошибкам в будущем, если какой-либо код за пределами вашего класса начнет возиться с его внутренними переменными.
Редактировать:
Казалось бы, наиболее очевидным решением было бы прекратить статическое соединение. Тогда ваш клиентский код мог бы выглядеть примерно так:
try{
// use using block around connection, calls dispose automatically when
// block ends...
using(var connectionWrapper = new Connexion_D()) {
var connectedConnection = connectionWrapper.GetConnected();
// do CRUD
}
}
catch{
// catching Error, avoid yellow page aspx
// Really you should probably be doing something with the exception (logging?)
// particularly since you go to the effort of throwing it from your Connection_D
// class.
}
Код вашего класса выглядит как:
/* Implement IDisposable to cleanup connection */
public class Connexion_D : IDisposable
{
public SqlConnection conn;
public SqlConnection GetConnected()
{
try
{
String strConnectionString = ConfigurationManager.ConnectionStrings["xxxxx"].ConnectionString;
conn = new SqlConnection(strConnectionString);
}
catch (Exception excThrown)
{
conn = null;
throw new Exception(excThrown.InnerException.Message, excThrown);
}
// Ouverture et restitution de la connexion en cours
if (conn.State == ConnectionState.Closed) conn.Open();
return conn;
}
public Boolean IsConnected
{
get { return (conn != null) amp;amp; (conn.State != ConnectionState.Closed) amp;amp; (conn.State != ConnectionState.Broken); }
}
public void CloseConnection()
{
// Libération de la connexion si elle existe
if (IsConnected) {
conn.Close();
conn = null;
}
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
// Close connection
}
}
Смотрите это для получения дополнительной информации о реализации IDisposable.
Комментарии:
1. Спасибо за ваш ответ, можете ли вы внести предложение? должен ли я использовать одноэлементный шаблон?
2. @user609511: Я обновил свой ответ с помощью подхода . Singleton может работать, но вам придется совместно использовать соединение между несколькими пользователями, что может вызвать проблемы при обновлении транзакций / повторном подключении и т.д. Я думаю, вам лучше иметь несколько подключений для поддержания изоляции. Возможно, вы захотите взглянуть на пул соединений, если в конечном итоге у вас возникнут проблемы с производительностью, но я бы побеспокоился об этом, если вы туда доберетесь.