2010-11-08 132 views
1

我在ASP.NET 4.0和C#中使用.NET 4.0(會不會是C#4.0?)。對方法重載感到困惑

我要插入一些數據我的SQL Server數據庫中,我有一個方法,像這樣來處理這個問題:

public int InsertTrade(
    string symbol, 
    string tradeSetupId, 
    int tradeTypeId, 
    decimal lotsPerUnit, 
    string chartTimeFrame, 
    int tradeGrade, 
    int executionGrade, 
    int MFEPips, 
    int MAEPips, 
    decimal pctAccountRisked 
    ) 
{ 
    SqlCommand cmd = new SqlCommand("usp_InsertTrade"); 
    cmd.Parameters.AddWithValue("@symbol", symbol); 
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked); 
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId); 
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit); 
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame); 
    cmd.Parameters.AddWithValue("@MAEPips", MAEPips); 
    cmd.Parameters.AddWithValue("@MFEPips", MFEPips); 
    cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade); 
    cmd.Parameters.AddWithValue("@executionGrade", executionGrade); 
    return (InsertData(cmd, "trade")); 
} 

有一些非必填字段:tradeGrade,executionGrade,MFEPips,MAEPips。 usp_InsertTrade存儲過程將這些可選參數作爲NULLable公開。什麼是在C#中編碼的最佳方式?我正在學習編程,所以如果你能提供有關最佳實踐的指導,那將是非常好的。

這裏是存儲過程的參數usp_InsertTrade:

CREATE procedure [dbo].[usp_InsertTrade] 
@symbol char(6), 
@tradeSetupId varchar(10), 
@tradeTypeId int, 
@lotsPerUnit decimal(18,1), 
@chartTimeFrame varchar(5), 
@tradeGrade smallint = NULL, 
@executionGrade smallint = NULL, 
@MFEPips int = NULL, 
@MAEPips int = NULL, 
@pctAccountRisked decimal(3,2) 
AS 

非常感謝。

UPDATE

我已經改變了我的工作,使得可選參數是在底部。像這樣:

public int InsertTrade(
    string symbol, 
    string tradeSetupId, 
    int tradeTypeId, 
    decimal lotsPerUnit, 
    string chartTimeFrame, 
    decimal pctAccountRisked, 
    int? tradeGrade, 
    int? executionGrade, 
    int? MFEPips, 
    int? MAEPips 
    ) 
{ 
    SqlCommand cmd = new SqlCommand("usp_InsertTrade"); 
    // required parameters 
    cmd.Parameters.AddWithValue("@symbol", symbol); 
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId); 
    cmd.Parameters.AddWithValue("@tradeTypeId", tradeTypeId); 
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit); 
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame); 
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked); 

    // optional parameters 
    if (MAEPips.HasValue) 
     cmd.Parameters.AddWithValue("@MAEPips", MAEPips); 
    if (MFEPips.HasValue) 
     cmd.Parameters.AddWithValue("@MFEPips", MFEPips); 
    if (tradeGrade.HasValue) 
     cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade); 
    if (executionGrade.HasValue) 
     cmd.Parameters.AddWithValue("@executionGrade", executionGrade); 
    return (InsertData(cmd, "trade")); 
} 

當我使用此代碼調用該函數:

DBUtil DB = new DBUtil(); 
int tradeId = DB.InsertTrade (
    ddlSymbols.SelectedValue, 
    ddlTradeSetups.SelectedValue, 
    ddlTradeTypes.SelectedValue, 
    decimal.Parse(txtLotsPerUnit.Text), 
    ddlTimeFrames.Text, 
    decimal.Parse(txtAcctRisk.Text)); 

我得到這個錯誤:

No overload for method 'InsertTrade' takes 6 arguments 
+0

你在參數聲明中缺少= null - 這是導致你的錯誤。 – Paddy 2010-11-08 11:40:43

+0

@Paddy - 謝謝,需要咖啡...... – 2010-11-08 11:44:41

+0

另外,我認爲你可能需要將空值轉換爲空值類型。例如; '詮釋? tradeGrade =(int?)null'。 – 2010-11-08 11:46:12

回答

5

在C#4.0中,你可以使用optional parametersnullable types

public int InsertTrade(
    string symbol, 
    string tradeSetupId, 
    int tradeTypeId, 
    decimal lotsPerUnit, 
    string chartTimeFrame, 
    decimal pctAccountRisked, 
    int? tradeGrade = null, 
    int? executionGrade = null, 
    int? MFEPips = null, 
    int? MAEPips = null 
    ) 
{ 
    SqlCommand cmd = new SqlCommand("usp_InsertTrade"); 
    cmd.Parameters.AddWithValue("@symbol", symbol); 
    cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked); 
    cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId); 
    cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit); 
    cmd.Parameters.AddWithValue("@tfCode", chartTimeFrame); 
    if(MAEPips.HasValue) 
     cmd.Parameters.AddWithValue("@MAEPips", MAEPips); 
    if(MFEPips.HasValue) 
     cmd.Parameters.AddWithValue("@MFEPips", MFEPips); 
    if(tradeGrade.HasValue) 
     cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade); 
    if(executionGrade.HasValue) 
     cmd.Parameters.AddWithValue("@executionGrade", executionGrade); 
    return (InsertData(cmd, "trade")); 
} 

有了這麼多參數,您可能需要考慮重構introduce parameter object - 它將使您的代碼在未來更易於閱讀和修改。

+0

謝謝,請你看看我的問題的更新部分?我收到一個錯誤,我不知道爲什麼。 – 2010-11-08 11:38:51

+0

@Mark Allison - 您已將參數設置爲_nullable_ only('int?MFEPips,')。我也將它們設置爲_optional_('int?MFEPips = null,')。看到額外的'= null'? – Oded 2010-11-08 11:42:31

+0

謝謝,現在工作很好。我將不得不去研究你所談論的參數對象。 – 2010-11-08 11:45:41

0

你可以在參數中使用空的值,並檢查在添加參數之前的值,這樣,如果未提供該值,它將使用存儲的proc的默認值:

public int InsertTrade(
    ... 
    int? executionGrade, 
    ... 
    ) 
{ 
    SqlCommand cmd = new SqlCommand("usp_InsertTrade"); 
    ... 
    if(executionGrade.HasValue) 
     cmd.Parameters.AddWithValue("@executionGrade", executionGrade); 
    return (InsertData(cmd, "trade")); 
} 
+0

當然,他不需要檢查它是否有價值,因爲它會直接傳遞給存儲過程,爲空或以其他方式? – 2010-11-08 11:03:37

+0

@ Moo-Juice SQL'NULL'與C#'null'是不同的東西。要在C#中提到一個SQL'NULL',你需要說'DBNull.Value'。在這裏,由於我們想要的存儲區定義中的默認值是'NULL',最簡單的事情就是不說任何話。 – AakashM 2010-11-08 11:08:31

+0

@ Moo-Juice - 其中的特點是,即使不添加參數,它也會使用Stored Proc開發人員選擇的任何內容作爲默認參數 - 不一定爲null。 – Jamiec 2010-11-08 11:28:16

0

查看可空類型此鏈接:http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

總之,聲明你的函數爲:

public int InsertTrade(
    string symbol, 
    string tradeSetupId, 
    int tradeTypeId, 
    decimal lotsPerUnit, 
    string chartTimeFrame, 
    int? tradeGrade, 
    int? executionGrade, 
    int? MFEPips, 
    int? MAEPips, 
    decimal pctAccountRisked 
    ) 
3

我會創建一個struct爲了封裝參數。

這裏是我可能會想想可行的方法:

  1. 可選參數。您可以使用C#4.0語法(此功能已經存在於VB中,但最近添加到C#中)使用一些可選參數定義方法。缺點:你受限於如何使用可選參數。只有最後一個參數可以選擇。我的意思是,如果您有(姓名,地址,電話)作爲參數,按此順序,您不能跳過地址並設置名稱
  2. 結構。如前所述,這是我最喜歡的方式。您可以設置任何空值,但是你必須創建一個struct每種方法
  3. 定義重載:最壞的方法是定義一個過載每個組合則params的,這是不可行的大參數集合
  4. 對象數組:僅在全部參數具有不同類型時纔可行。您可以根據對象數組中的每個條目的類型確定參數。
  5. Dictionary<string,object>:另一個有趣的方法。每個條目映射用鑰匙

希望能一直幫助

+0

哇,謝謝,我不知道有這麼多方法去皮膚貓! – 2010-11-08 11:09:28

1

我會創造一個擴展方法來擺脫對可空變量的重複檢查。擴展方法看起來是這樣的:

public static class SqlCommandExtensions 
{ 
    public static void AddNullableInParameter<T>(this SqlCommand command, string columnName, Nullable<T> value) where T : struct 
    { 
     if (value.HasValue) 
     { 
      command.Parameters.AddWithValue(columnName, value.Value); 
     } 
    } 
} 

現在你可以只寫command.AddNullableInParameter("@yourParameter", YourNullableType);代替所有的if語句的。