2017-04-05 13 views
0

的代碼是這樣的:爲了減少數據庫執行時間,我的GetEmails()方法可能會發生什麼變化?

public class Email 
{ 
    public string MailAddress {get;set;} 
    public string MailOwner {get;set;} 
    public int MailSended {get;set;} 
    public int MailReceived {get;set;} 
} 

public class EmailList 
{ 
    public List<Email> Items {get; private set;} 
    private IDBConnection _connection; 


    public EmailList(IDBConnection connection) 
    { 
     _connection = connection; 
    } 

    public List<Email> GetEmails(int customerId) 
    { 
     var emailList = new List<Email>(); 
     var sql = "SELECT * FROM EmailsAddress WHERE Id = '" + customerId + "'"; 

     using (var ObjectToAccessDatabaseAndStoreResultsIntoDataTable = new ObjectToObtainDbResultsIntoDataTable(_connection, sql)) 
     { 
      foreach(DataRow row in ObjectToAccessDatabaseAndStoreResultsIntoDataTable.Datatable) 
      { 
       var email = new Email{ 
       MailAddress = Convert.ToString(row["MailAddress"]); 
       MailOwner = Convert.ToString(row["MailOwner"]); 
       MailSended = Convert.ToInt32(row["MailSended"]); 
       MailReceived = Convert.ToInt32(row["MailReceived"]); 
      } 

      emailList.Add(email); 
     }  
     return emailList; 
    } 
} 

GetEmails()被多次調用來檢索電子郵件地址,爲即2000個客戶,需要花費很長的時間來恢復。使用SQL Server Profiler,我發現大部分時間都是針對GetEmails()例程。

爲什麼GetEmails()程序需要這麼長時間?我正在使用SQL Server。

+0

它看起來不正確的ID來獲得郵件地址,應該不是像'其中客戶ID = ...'? – Silvermind

+0

我做了一個快速示例代碼。Obiviuosly我的代碼不是這樣的,但它的工作是這樣的。 – CRK

回答

2
  1. 是否在你的EmailsAddress表的編號列有此列的索引?如果不是,加一個會加快速度。

  2. 你總是應該使用參數化查詢,不串concatination - 它允許數據庫來優化你的查詢,而且更重要的是,可以保護你免受SQL注入攻擊(雖然不是你的情況有一個整數類型有關)。

    var command = 
        new SqlCommand("SELECT * FROM EmailsAddress WHERE Id = @Id;", db); 
    command.Parameters.AddWithValue("@Id", yourTextValue); 
    command.ExecuteQuery(); 
    
  3. 帕特里克·霍夫曼說什麼,通過分組ID或使用連接查詢的客戶會方式更有效時,讓你的客戶mailaddresses。

/編輯:這裏是一個查詢請求多個ID的例子:

var command = 
    new SqlCommand("SELECT * FROM EmailsAddress WHERE Id IN (@Id1,@Id2,@Id3);", db); 
command.Parameters.AddWithValue("@Id1", 1); 
command.Parameters.AddWithValue("@Id2", 54); 
command.Parameters.AddWithValue("@Id2", 96); 
command.ExecuteReader(); 

或者無視我自己的建議使用參數:

var sql = "SELECT * FROM EmailsAddress WHERE Id IN (1,54,96)"; 

示例在做這個一個循環,帶參數:

 var ids = new int[] { 1, 95, 46, 93, 98, 77 }; 
     var isFirst = true; 
     var commandBuilder = new StringBuilder("SELECT * FROM EmailsAddress WHERE Id IN ("); 
     var command = new SqlCommand(""); 
     for (var i = 0;i<ids.Length;i++) 
     { 
      if (!isFirst) commandBuilder.Append(","); 
      else isFirst = false; 
      var paramName = "@Id" + i; 
      commandBuilder.Append(paramName); 
      command.Parameters.AddWithValue(paramName, ids[i]); 
     } 
     commandBuilder.Append(")"); 
     command.CommandText = commandBuilder.ToString(); 
     command.ExecuteReader(); 

     // Read your result 
+0

你可以做一個例子? 「分組ID」是什麼意思?如果我能夠分組ID,如何將該組傳遞給查詢?例如,我希望來自2000客戶的電子郵件中沒有順序ID(1,54,1450等),因此它不能是範圍。 – CRK

+0

我添加了一個例子。 – Compufreak

+0

如果我有200個ID,該怎麼辦? – CRK

1

你能找到問題在哪裏嗎?

是的,你正在向數據庫發出2000條SQL語句,它必須一一解析並執行它們,而在這種情況下,一條SQL語句就足夠了。

你可以做什麼,這取決於數據庫的大小:

  • 負載一次的所有記錄。將它們存儲在緩存對象中,然後從該緩存中回答。當有很多行時,這可能是一個問題,而您只打算獲得一小部分記錄;
  • 一次加載多個客戶。如果您不想一次獲取整個表格,這可能會有所幫助,但確實有一個緊密的循環,它反覆調用GetEmails方法。您可以傳入客戶ID列表並立即獲取這些ID。這將需要您的customerId上的in聲明。
+0

所以問題不是電子郵件類的多個實例?你可以用代碼做一個例子嗎? – CRK

+0

不是。這些情況不是問題。我無法舉出所有提到的要點。每個產品的文檔都會幫助你。 –

+0

你能舉一個例子,至少對第二點來說嗎?我不明白你的意思 – CRK

1

你可以得到電子郵件地址列表中的客戶這樣

public List<Email> GetEmails(List<int> listCustomerId) 
    { 
     var emailList = new List<Email>(); 
     var sql = "SELECT * FROM EmailsAddress WHERE Id IN (" + string.Join(",", listCustomerId) + ")"; 

     using (var ObjectToAccessDatabaseAndStoreResultsIntoDataTable = new ObjectToObtainDbResultsIntoDataTable(_connection, sql)) 
     { 
      foreach (DataRow row in ObjectToAccessDatabaseAndStoreResultsIntoDataTable.Datatable) 
      { 
       var email = new Email 
       { 
        MailAddress = Convert.ToString(row["MailAddress"]); 
        MailOwner = Convert.ToString(row["MailOwner"]); 
        MailSended = Convert.ToInt32(row["MailSended"]); 
        MailReceived = Convert.ToInt32(row["MailReceived"]); 
       } 

       emailList.Add(email); 
      } 

      return emailList; 
     } 
    } 
相關問題