помогите уменьшить количество подключений к базе данных - PullRequest
1 голос
/ 15 сентября 2010

У меня есть список строк, которые являются просто номерами счетов.Я перечисляю этот список, чтобы получить подробную информацию о каждом счете из базы данных.Этот список может быть размером от 700 до 1000.То, как я это делаю сейчас, приводит к 700-1000 подключений к базе данных.это занимает слишком много времени, чтобы завершить, есть ли лучший способ сделать это, о котором я просто не знаю?Любые указатели были бы хорошими.

вот пример моего перечисления

foreach(string i in invoiceList)
{
  Invoice inv = invoiceData.GetInvoice(i);
  //do something with the invoice
}

тогда вот пример моего метода доступа к данным с использованием ado.net

public Invoice GetInvoice(string invoice)
{
      SqlConnection con = new SqlConnection(//connection string);
      SqlCommand cmd = new SqlCommand("dbo.getInvoices", con);
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add("invoice", SqlDbType.VarChar).Value = invoice;
      SqlDataReader dr;
      Invoice inv = new Invoice();
      try{
            con.Open();
            dr = cmd.ExecuteReader
            while(dr.read())
            {
                 //assign values from the database fields
            }


      }
      catch{}
      finally{con.close();}

}

так что в основном метод getInvoice вызывается 1000 раз, каждый раз открывая новое соединение.Что является лучшим (более быстрым) способом сделать это.Спасибо!

Ответы [ 5 ]

1 голос
/ 15 сентября 2010

Что-то вроде этого может быть улучшением.

public List<Invoice> GetInvoices(List<string> invoiceList) {
  List<Invoice> invoices = new List<Invoice>();

  Invoice inv;
  SqlDataReader dr;

  using (SqlConnection con = new SqlConnection(//connection string)) {
    using(SqlCommand cmd = new SqlCommand("dbo.getInvoices", con)) {
      cmd.CommandType = CommandType.StoredProcedure;
      SqlParameter param = cmd.Parameters.Add("invoice", SqlDbType.VarChar);

      foreach(string i in invoiceList) {
        inv = new Invoice();
        param.Value = i;
        using (dr = cmd.ExecuteReader()) {
          while(dr.read())
          {
            // assign values from the database fields
            inv.Property = dr.GetString(0);

            // Add invoice to the result list
            invoices.Add(inv);
          }
        }
      }
    }
  }

  return invoices;
}

Тогда вы можете использовать этот метод, как так ...

var invoiceList = new List<string> { "123", "456", "789" };
var invoices = GetInvoices(invoiceList);
foreach(var i in invoices) {
  Console.WriteLine(i.SomeInvoiceProperty);
}
1 голос
/ 15 сентября 2010

Я пропускаю conn.Close() внутри вашего блока попытки.

Если он действительно отсутствует, это может быть вашей проблемой: вы продолжаете устанавливать новые подключения все время.Итак, закройте его в блоке try / finally.

Но если это была опечатка в опубликованном коде, то я не думаю, что ваша проблема связана с подключением (ями), ADO.NET использует ConnectionPooling, поэтому вы сохраняете «реальное» соединение открытымдаже когда вы говорите conn.Close ().

Другой проблемой будет выполнение запроса для каждого счета.Это тоже дорого.Но так как вы, кажется, используете SP, это не так легко преодолеть.Здесь было бы полезно использовать оператор SELECT, заканчивающийся WHERE Id IN (a, b, c, d).Это позволит вам группировать счета (получить 5 или 20 с 1 запросом.

1 голос
/ 15 сентября 2010

Просто поместите все номера накладных в оператор IN и запустите этот оператор select в одном соединении.

1 голос
/ 15 сентября 2010

Вы можете поместить код открытия и закрытия соединения за пределы цикла.Это сделало бы у вас только одно соединение с базой данных.Но это одно соединение будет открыто какое-то время.Это компромисс.Одно соединение открыто в течение длительного времени или множество соединений открывается и закрывается.

Я также заметил, что вы не закрываете свое соединение в коде попытки.Может быть, попробуйте это.

public Invoice GetInvoice(string invoice)
{
      SqlConnection con = new SqlConnection(//connection string);
      SqlCommand cmd = new SqlCommand("dbo.getInvoices", con);
      cmd.CommandType = CommandType.StoredProcedure;
      cmd.Parameters.Add("invoice", SqlDbType.VarChar).Value = invoice;
      SqlDataReader dr;
      Invoice inv = new Invoice();
      try{
            con.Open();
            dr = cmd.ExecuteReader
            while(dr.read())
            {
                 //assign values from the database fields
            }
      }
      catch{}
      finally
      {
        con.Close();
      }
}
0 голосов
/ 15 сентября 2010

Я полагаю, что вы, возможно, захотите рассмотреть другой подход, если вы последовательно обрабатываете от 700 до 1000 или более номеров счетов за один раз, почему бы не отправить все номера счетов-фактур вниз в одном запросе вместо множества отдельных запросов.Например, вы можете использовать sql в списке, чтобы сделать это, как показано ниже.

select
 *
from
 ivoice_table
where
 invoice_table.invoice_number in (123,124,125,126,127,128 etc....)

Наслаждайтесь!

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