2016-09-30 3 views
0

Я вычисляю выдающийся баланс клиентов в C# Winforms. Код ниже работает, но он медленный. Есть ли способ улучшить его работу?MS SQL Query in C# - низкая производительность

public DataTable GetOutStandingCustomers() 
{ 
    decimal Tot = 0; 

    DataTable table = new DataTable(); 

    SqlConnection con = null; 
    try 
    { 

     table.Columns.Add("Code", typeof(Int32)); 
     table.Columns.Add("Name", typeof(string)); 
     table.Columns.Add("City", typeof(string)); 
     table.Columns.Add("Tot", typeof(decimal)); 


     string constr = ConfigHelper.GetConnectionString(); 

     string query = "SELECT Code, Name,City FROM Chart WHERE LEFT(CODE,3)='401' AND Code > 401001 "; 
     string query0 = " SELECT(SELECT ISNULL(SUM(SalSum.Grand),'0') FROM SalSum WHERE SalSum.Code = @Code) +(SELECT ISNULL(SUM(Journals.Amount),'0') FROM Journals WHERE Journals.DrCode = @Code) -(SELECT ISNULL(SUM(RSalSum.Grand),'0') FROM RSalSum WHERE RSalSum.Code = @Code) -(SELECT ISNULL(SUM(Journals.Amount),'0') FROM Journals WHERE Journals.CrCode = @Code)+(SELECT ISNULL(SUM(Chart.Debit),'0') FROM Chart WHERE Chart.Code = @Code) - (SELECT ISNULL(SUM(Chart.Credit), '0') FROM Chart WHERE Chart.Code = @Code)"; 

     Person per = new Person(); 

     con = new SqlConnection(constr); 

     SqlCommand com = new SqlCommand(query, con); 
     SqlCommand com0 = new SqlCommand(query0, con); 

        con.Open(); 

     SqlDataReader r = com.ExecuteReader(); 

     if (r.HasRows) 
     { 
      while (r.Read()) 
      { 

       per.Name = Convert.ToString(r["Name"]); 
       per.City = Convert.ToString(r["City"]); 
       per.Code = Convert.ToString(r["Code"]); 


       com0.Parameters.Clear(); 
       com0.Parameters.Add("@Code", SqlDbType.Int).Value = per.Code; 


       Tot = Convert.ToDecimal(com0.ExecuteScalar()); 


       if (Tot != 0) 
       { 
        table.Rows.Add(per.Code, per.Name, per.City, Tot); 
       } 

      } 
     } 
     r.Close(); 
     con.Close(); 

     return table; 
    } 
    catch (Exception) 
    { 
     throw new Exception(); 
    } 
} 
+1

Ну, какая часть является медленным? И почему вы ловите * полезное * исключение, только чтобы выбросить его без какой-либо информации? –

+0

Почему 2 команды SQL? –

+2

(По сути, это выглядит как проблема заключается в том, что вы делаете N + 1 запросы, когда вы должны быть просто использовать соединение ...) –

ответ

0

Проблема производительности из-за вас извлечь все данные с сервера и фильтров данных в клиенте с использованием комплекса вычисляется выражение, сумма из семи таблиц :

  if (Tot != 0) 
      { 
       table.Rows.Add(per.Code, per.Name, per.City, Tot); 
      } 

Это представляет собой накладные расходы по сети плюс вы вручную добавляете результат в строку данных по строке.

Предоставленное решение фильтруется на сервере на основе вычисленного выражения с использованием CROSS APPLY и автоматически создает данные, непосредственно связанные с DataReader.

Преимущества CROSS APPLY - это все столбцы, которые могут быть использованы для основного sql-запроса, поэтому вы можете фильтровать в столбце ToT, фильтрация выполняется на сервере (а не на клиенте).

public void SelctChart() 
{     
    string sql2 = @" 
     select c.Code, c.Name,c.City ,oo.T 
     from chart c 
     cross apply 
     (select c.code, 
      ( 
       (select ISNULL(SUM(SalSum.Grand),0) FROM SalSum WHERE SalSum.Code = c.code) 
      +(select ISNULL(SUM(j.Amount),0) FROM [dbo].[Jornals] j WHERE j.DrCode = c.code) 
      -(SELECT ISNULL(SUM(RSalSum.Grand),'0') FROM RSalSum WHERE RSalSum.Code = c.Code) 
      -(SELECT ISNULL(SUM(j.Amount),0) FROM [dbo].[Jornals] j WHERE j.CrCode = c.code) 
      +(SELECT ISNULL(SUM(c0.Debit),0) FROM [dbo].Chart c0 WHERE c0.Code = c.code) 
      - (SELECT ISNULL(SUM(c1.Credit), 0) FROM [dbo].Chart c1 WHERE c1.Code = c.code) 
      )T 
     ) oo 
    where 
     oo.T >0 
     and LEFT(c.CODE,3)='401' AND c.Code > 401001 
    "; 


     using (SqlConnection connection = new SqlConnection(connectionString)) 
     { 
      SqlCommand command = new SqlCommand(sql2, connection); 
      //in case you pass @code as a a parameter 
      //command.Parameters.Add("@code", SqlDbType.Int); 
      //command.Parameters["@code"].Value = code; 

      try 
      { 
       connection.Open(); 
       var reader = command.ExecuteReader(); 
       while (!reader.IsClosed) 
       { 
        DataTable dt = new DataTable(); 
        // Autoload datatable 
        dt.Load(reader); 
        Console.WriteLine(dt.Rows.Count); 

       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 
     } 
    } 

Вы можете изменить метод и передать код в качестве параметра

+0

Спасибо, его работа ........... –

+0

http://stackoverflow.com/questions/39858074/how-customise-nop-commerce-ewayhosted-plugin-for-other-payment-gateway –

0

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

ON Chart.Code = Salsum.Code 
ON Chart.Code = Journal.Code 

например. Вы также должны посмотреть на GROUP BY, потому что вы объединяете некоторые столбцы таблицы, используя SUM. Вам также может потребоваться убедиться, что код проиндексирован в запросах, которые вы запрашиваете. До тех пор, пока код часто запрашивается таким образом и сравнительно редко обновляется или вставляется в, вероятно, целесообразно индексирование столбца «Код» в этих таблицах. левого Соединение: https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx Индексация: https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx

Жаль, что я написал книгу о вас здесь, но оптимизация часто приводит к длительному ответу (особенно с SQL).

tldr; Используйте LEFT JOIN, группируя по коду

индекс столбцы Код

+0

Я пытаюсь выполнить запрос соединения, но его не удается. Приведите пример с моим кодом. –

 Смежные вопросы

  • Нет связанных вопросов^_^