2017-01-17 104 views
2

在我的主要形式,我已經實現了這個代碼..傳遞多個的SqlParameter到方法

void SampleMethod(string name, string lastName, string database) 
{ 
     SqlParameter sqlParam = new SqlParameter(); 
     sqlParam.ParameterName = "@name"; 
     sqlParam.Value = name; 
     sqlParam.SqlDbType = SqlDbType.NVarChar; 

     SqlParameter sqlParam1 = new SqlParameter(); 
     sqlParam1.ParameterName = "@lastName"; 
     sqlParam1.Value = lastName; 
     sqlParam1.SqlDbType = SqlDbType.NVarChar; 

     SqlParameter sqlParam2 = new SqlParameter(); 
     sqlParam2.ParameterName = "@database"; 
     sqlParam2.Value = database; 
     sqlParam2.SqlDbType = SqlDbType.NVarChar; 

     SampleClass sampleClass = new SampleClass(new DBConn(@serverName, tableName, userName, password)); 
     sampleClass.executeStoredProc(dataGridView1, "sp_sampleStoredProc", sqlParam, sqlParam1, sqlParam2); 
} 

在我SampleClass,我有這種方法。

public DataGridView executeStoredProc(DataGridView dtgrdView, string storedProcName, params SqlParameter[] parameters) 
{ 
     try 
     { 
      DataTable dt = new DataTable(); 
      sqlDA = new SqlDataAdapter(storedProcName, sqlconn); 
      sqlDA.SelectCommand.CommandType = CommandType.StoredProcedure; 
      sqlDA.SelectCommand.CommandTimeout = 60; 

      // Loop through passed parameters 
      if (parameters != null && parameters.Length > 0) 
      { 
       foreach (var p in parameters) 
        sqlDA.SelectCommand.Parameters.Add(p); 
      } 

      sqlDA.Fill(dt); 
      dtgrdView.DataSource = dt; 
      sqlconn.Close(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
      sqlconn.Close(); 
     } 

     return dtgrdView; 
} 

我所試圖做的是避免多次

SqlParameter sqlParam = new SqlParameter() 
在我的代碼

,我已經嘗試了這個問題,讓許多解決方案,但我沒有得到正確的答案。我也試圖研究這一點,但我仍然無法得到正確的答案。

請不要介意我的命名約定和其他代碼,因爲我故意改變其中的很多:)謝謝。

+0

爲什麼你要避免呢?你想要達到什麼目的? –

+0

您可以使用'Parameters.Add'創建參數,但是您的代碼被明確寫入以將各個參數傳遞給'executeStoredProc'。這有點自相矛盾。爲什麼你想要避免多個參數? –

+0

嘗試爲數據訪問創建單獨的類,其中只返回SqlDataAdapter(DataTable,DataSet)的結果。您可以使您的數據訪問層方法以這種方式參數SqlCommand,從而避免擁有多個Sql參數。你可以檢查這個問題的答案,我寫了簡單的DAL-> http://stackoverflow.com/questions/25816609/checking-user-name-or-user-email-already-exists/25817145#25817145。你可以重新使用它。同樣在目前的格式中,這個問題太廣泛了。 – mybirthname

回答

2

作爲您的解決方案的替代方案,請嘗試使用已有的一個,而不是使用Dapper(https://github.com/StackExchange/dapper-dot-net)。

如果你的存儲過程或查詢需要它,你仍然需要使用多個參數,但是這對你來說是很好的抽象,這將明確地減少代碼量。

void SampleMethod(string name, string lastName, string database) 
{ 
    using(var connection = new SqlConnection(MY_CONNECTION_STRING)) 
    { 
     var resultListOfRows = connection.Query<ReturnObject>(MY_STORED_PROCEDURE, new { 
      name = name, 
      lastName = lastName, 
      database = database}, commandType: System.Data.CommandType.StoredProcedure); 
    } 
} 
+1

它應該是'查詢'不'執行' –

+0

@Panagiotis Kanavos,固定...謝謝 – vidriduch

0

單獨在一個地方(放sqladapter,SqlCommand的等在一個地方),然後封裝你的命令中的參數,如下面提到,你並不需要單獨申報的SqlParameter,添加您的數據庫邏輯,裏面的參數列表。

cmdToExecute.Parameters.Add(new SqlParameter("@parameter", value)); 

看看完整的示例如下

public DataTable ProdTypeSelectAll(string cultureCode) 
    { 
     SqlCommand cmdToExecute = new SqlCommand(); 
     cmdToExecute.CommandText = "dbo.[pk_ProdType_SelectAll]"; 
     cmdToExecute.CommandType = CommandType.StoredProcedure; 
     DataTable toReturn = new DataTable("ProdType"); 
     SqlDataAdapter adapter = new SqlDataAdapter(cmdToExecute); 
     cmdToExecute.Connection = _mainConnection; 
     cmdToExecute.Parameters.Add(new SqlParameter("@CultureName", cultureCode)); 
     _mainConnection.Open(); 
     adapter.Fill(toReturn); 
     return toReturn; 
} 
+0

你的代碼*會創建新的參數。 –

+0

是的,但方式不同。 –

0

您可以使用SqlParameter Constructor (String, Object)。替換:

sampleClass.executeStoredProc(dataGridView1, 
     "sp_sampleStoredProc", 
     sqlParam, 
     sqlParam1, 
     sqlParam2); 

有了:

sampleClass.executeStoredProc(dataGridView1, 
     "sp_sampleStoredProc", 
     new SqlParameter("@name", (object)name), 
     new SqlParameter("@lastName", (object)lastName), 
     new SqlParameter("@database", (object)database)); 

但是,這樣做是不太可能使你的代碼的任何速度,反而會降低可讀性。

1

首先,最簡單的選擇是使用像Dapper這樣的microORM,並檢索強類型的集合。 Gridviews可以綁定到任何東西,包括強類型的集合。所有這些代碼可能會變成:

using(var con=new SqlConnection(myConnectionString)) 
{ 
    con.Open(); 
    var result= connection.Query<ResultClass>("sp_MySproc", 
         new { Name= name, LastName= lastName,Database=database}, 
         commandType: CommandType.StoredProcedure); 
    return result; 
} 

即使使用原始ADO.NET的時候,你可以在一行中使用appropriate constructor創建的SqlParameter。例如,你可以創建一個新的nvarchar(n)參數有:

var myParam=new SqlParameter("@name",SqlDbType.NVarchar,20); 

var myParam=new SqlParameter("@name",SqlDbType.NVarchar,20){Value = name}; 

一個更好的想法,雖然是隻一次創建SqlCommand對象和重用。一旦你有一個初始化SqlCommand對象,你可以簡單地設置一個新的連接,改變參數值,例如:

public void Init() 
{ 
    _loadCustomers = new SqlCommand(...); 
    _loadCustomers.Parameters.Add("@name",SqlDbType.NVarChar,20); 
    ... 
} 

//In another method : 
using(var con=new SqlConnection(myConnectionString) 
{        
    _loadCustomers.Connection=con; 
    _loadCustomers.Parameters["@name"].Value = myNameParam; 
    con.Open(); 
    using(var reader=_load.ExecuteReader()) 
    { 
    //... 
    } 
} 

你可以做一個SqlDataAdapter同樣的事情,其實這就是如何Windows窗體和數據適配器意味着自.NET 1.0起使用。

而不是每次你想填補你的網格創建一個新的,而不是創建一個單一的並通過在執行前設置連接和參數來重用它。您可以使用SqlDataAdapter(SqlCommand)構造函數使事情更清潔:

public void Init() 
{ 
    _loadCustomers = new SqlCommand(...); 
    _loadCustomers.Parameters.Add("@name",SqlDbType.NVarChar,20); 
    .... 
    _myGridAdapter = new SqlDataAdapter(_loadCustomers); 
    ... 
} 

,並調用它是這樣的:

using(var con=new SqlConnection(myConnectionString)) 
{ 
    _myGridAdapter.SelectCommand.Connection=con; 
    _myGridAdapter.SelectCommand.Parameters["@name"].Value =....; 
    con.Open(); 

    var dt = new DataTable(); 
    _myGridAdapter.Fill(dt); 
    dtgrdView.DataSource = dt; 
    return dtgrdView; 
}