Azure SQL - соединения с одной или несколькими БД? - PullRequest
2 голосов
/ 29 января 2012

У меня есть клиент-серверное приложение, где на стороне сервера находится служба Azure WCF с данными в базе данных SQL Azure.Клиентами являются приложения Windows Phone 7 silverlight.Клиент и сервер связываются через WCF.Сервер предоставляет клиенту данные, которые хранятся в базе данных SQL Azure.

Недавно я столкнулся с некоторыми проблемами с пулами.Я создавал новый объект каждый раз, когда поступал запрос клиента.Я не закрывал эти соединения и очень скоро обнаружил исключение:

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

Мой вопрос - как обрабатывать объект подключения к БД?Должен ли я создать один объект подключения для каждого запроса клиента или я должен создать одноэлементный объект, который должен обрабатывать все обращения к БД?Возможно ли это вообще - не истекает ли время ожидания соединения объекта или что-то в этом роде?

Я использую объект SQLConnection:

private static SqlConnection connection
        {
            get
            {
                SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder
                {
                    DataSource = DB_SOURCE,
                    InitialCatalog = DB_NAME,
                    Encrypt = false,
                    TrustServerCertificate = false,
                    UserID = DB_USER,
                    Password = DB_PASS,
                };
                SqlConnection c = new SqlConnection(connectionStringBuilder.ToString());
                c.Open();
                return c;
            }
        }

        public static void execute(String query)
        {
            try
            {
                SqlCommand com = new SqlCommand(query, connection);
                com.ExecuteNonQuery();
            }
            finally
            {
                connection.Close();
            }
        }

Ответы [ 6 ]

1 голос
/ 30 января 2012

Соединения SQL объединяются по умолчанию. Поэтому вы должны «создавать» их, когда они вам нужны, и уничтожать их, когда они будут выполнены. (Ваш код будет проще, если вы используете using вместо try/finally.)

0 голосов
/ 31 января 2012

Я согласен с ответами Виктора Зихлы, Тобиаса и Эрве Роггеро. Они объясняют это:

  1. Ваш получатель (connect свойство) не возвращает ожидаемый исходный SqlConnection, следовательно, исходное соединение не закрывается.
  2. Вы должны создавать SqlConnection s, когда они вам нужны, держать их открытыми только столько, сколько вам нужно, и закрывать их, когда вы закончите.

Вот полное решение:

private static string _connectionString = string.Empty;

private static string connectionString
{
  get
  {
    if (string.IsNullOrEmpty(_connectionString))
    {
      _connectionString = new SqlConnectionStringBuilder
      {
        DataSource = DB_SOURCE,
        InitialCatalog = DB_NAME,
        Encrypt = false,
        TrustServerCertificate = false,
        UserID = DB_USER,
        Password = DB_PASS,
      }.ToString();
    }

    return _connectionString;
  }
}

public static void Execute(String query)
{
  using (SqlConnection connection = new SqlConnection(connectionString))
  using (SqlCommand command = new SqlCommand(query, connection))
  {
    connection.Open();
    command.ExecuteNonQuery();
  }
}
0 голосов
/ 31 января 2012

Я согласен с Оливером, что вы должны создавать связи и закрывать их каждый раз; пул соединений позаботится обо всем остальном Также вы должны держать свои соединения открытыми в течение минимального количества времени. Каждый раз закрывайте свои соединения, как можно быстрее, и проверяйте, совпадает ли строка подключения в одно и то же время, чтобы ваша стратегия пула соединений работала.

0 голосов
/ 29 января 2012

Одно соединение на запрос - это слишком много соединений.(одно крайнее) Одноэлементное соединение - это слишком мало соединений.

Вам нужно иметь соединение на сеанс пользователя.Самый простой способ сделать это - использовать контейнер IoC, например Ninject, и запросить соединение через контейнер.

0 голосов
/ 29 января 2012

Проблема в том, что вы закрываете не соединение, которое использовали для команды, а новое, созданное вами только для его закрытия.

Тело вашего execute метода должно быть следующим:

var con = connection;
try 
{ 
    SqlCommand com = new SqlCommand(query, con); 
    com.ExecuteNonQuery(); 
} 
finally 
{ 
    con.Close(); 
} 
0 голосов
/ 29 января 2012

Вы ссылаетесь на connection дважды в своем коде, и из-за этого у вас есть два разных соединения, так как ваш get ter всегда создает новое соединение!

Таким образом, последний создается, а затем немедленно удаляется, но первый не закрывается.

Перепишите ваш код как минимум на:

public static void execute(String query) {
    SqlConnection c = null;
    try { 
      c = connection;
      using ( SqlCommand com = new SqlCommand(query, c);                 
         com.ExecuteNonQuery();
    }
    finally {
       if ( c!=null)
         c.Close();
    }
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...