2017-05-30 53 views
0

我需要找到一個方法來檢索出以下查詢參數檢索輸出參數:如何使用文本命令

query = @"declare @p7 int 
      exec some_sproc @[email protected] 
      select @p7"; 

sqlCommand.CommandText = query; 
sqlCommand.CommandType = CommandType.Text; 

我厭倦了加入SQL paramater但隨後整個代碼簡單地包裹着exec sp_executesql和該參數已添加。這根本行不通。你知道我如何在C#端獲得@ p7的價值嗎?

我的存儲過程使用表值參數,但是默認情況下它被評估爲

declare @p11 acco.SomeUDT 
insert into @p11 values(1,'2017-06-15 00:00:00',64.73) 
insert into @p11 values(1,'2017-06-15 00:00:00',1.30) 

但我的本意是讓下面的語法:

declare @p11 acco.SomeUDT 
insert into @p11 values(1,'2017-06-15 00:00:00',64.73), (1,'2017-06-15 00:00:00',1.30) 

這就是爲什麼我建立手動SQL代碼。所以我們有:

query = @"declare @p7 int 

      declare @p11 acco.SomeUDT 
      insert into @p11 values(1,'2017-06-15 00:00:00',64.73), (1,'2017-06-15 00:00:00',1.30) 

      exec some_sproc @[email protected], @[email protected] 
      select @p7"; 
sqlCommand.CommandText = query; 
sqlCommand.CommandType = CommandType.Text; 

如果我使用存儲過程類型和SQL參數比我得到第一個語法。

所有的作品,但我需要映射出參數@SomeArg和我有這個問題。

+1

這看起來像一個探查器跟蹤複製/粘貼...。文本將通過sp_executesql的電話,你會需要添加更多的細節到你的問題來得到我想的答案。 –

+1

似乎有一個相當離奇的要求,即您不得不使用命令類型文本來執行過程。爲什麼不能按照預期的方式使用存儲過程? –

+0

您可以使用ADO.NET創建和使用表值參數。您也可以定義輸出參數。沒有理由使用此語法 –

回答

0

您應該能夠通過簡單地不申報@ P7在查詢中,而是將其作爲參數傳遞給SQL的CommandText

query = @"declare @p11 acco.SomeUDT 
      insert into @p11 
      values(1,'2017-06-15 00:00:00',64.73), (1,'2017-06-15 00:00:00',1.30) 
      exec some_sproc @[email protected], @[email protected];"; 

sqlCommand.CommandText = query; 
sqlCommand.CommandType = CommandType.Text; 
sqlCommand.Parameters.Add("@p7", SqlDbType.Int).Direction = ParameterDirection.Output; 
sqlCommand.ExecuteNonQuery(); 

Console.WriteLine(sqlCommand.Parameters["@p7"].Value); 

另外,如果是在你的程序的輸出參數來做到這一點那麼你可能要使用:

exec some_sproc @[email protected] OUT, @[email protected]; 
          ^^^ 

編輯

如果您有任何關於鮑比牛逼任何問題ABLES,轉換的問題或全部原因這是一個壞主意來構造SQL字符串這樣,你可以在C#創建表,並將其作爲參數傳遞太:

var table = new DataTable(); 
// TODO: Add the correct column names for your TVP here 
table.Columns.Add("Column1", typeof(int)); 
table.Columns.Add("Column2", typeof(DateTime)); 
table.Columns.Add("Column3", typeof(decimal)); 

table.Rows.Add(1, new DateTime(2017, 6, 15), 64.73); 
table.Rows.Add(1, new DateTime(2017, 6, 15), 1.3); 

sqlCommand.CommandText = "some_sproc"; 
sqlCommand.CommandType = CommandType.StoredProcedure; 
sqlCommand.Parameters.Add("@SomeArg", SqlDbType.Int).Direction = ParameterDirection.Output; 

var tvp = sqlCommand.Parameters.Add("@SomeUDTArg", SqlDbType.Structured); 
tvp.TypeName = "acco.SomeUDT"; 
tvp.Value = table; 

sqlCommand.ExecuteNonQuery(); 

Console.WriteLine(sqlCommand.Parameters["@SomeArg"].Value); 
+0

爲什麼不將表值參數作爲ADO.NET參數傳遞? –

+0

因爲沒有什麼可以表明在問題中這是必要的。在c#中創建和填充表格並將其作爲參數傳遞是更加努力的,並且如果值不是來自c#,那麼這種額外的努力沒有意義。 – GarethD

+0

Bobby表格,轉換問題或所有爲什麼構建這樣的SQL字符串是個壞主意的原因呢? –

0

此存儲過程使用表值參數作爲輸入並填充輸出參數。沒有理由填寫劇本中的TVP,你可以填寫在客戶端。

事實上,這是使用TVP的主要好處之一。在服務器端構建TVP會將其拋棄。

sqlCommand.CommandText = "some_sproc"; 
sqlCommand.CommandType = CommandType.StoredProcedure; 

//Create the out parameter 
var outParam=sqlCommand.Parameters.Add("@SomeArg", SqlDbType.Int); 
outParam.Direction = ParameterDirection.Output; 

//Set the TVP value 
var tvpParam=sqlCommand.Parameters.Add("@SomeUDTArg",SqlDbType.Structured); 
tvpParam.Value=myTable; 

//Run it 
sqlCommand.ExecuteNonQuery(); 


//And read the results 
var result=outParam.Value; 

myTable可以是強類型的DataTable或在運行時創建的DataTable。我很懶,所以我會用ToDataTable擴展方法從MoreLinq包從一個強類型集合創建一個DataTable:

public class MyRecord 
{ 
    public int ID{get;set;} 
    public DateTime Date {get;set;} 
    public decimal Value {get;set;} 
    public MyRecord(int id,DateTime date,decimal value){....} 
} 

...

var myValues=new List<MyRecord> 
      { 
       new MyRecord(1,new DateTime(2017,6,15),64.73m), 
       new MyRecord(1,new DateTime(2017,6,15),1.39m) 
      }; 

var myTable=myValues.ToDataTable(); 

如果字段名UDT和屬性名稱匹配,不需要其他更改。

如果您想將一組記錄用作默認TVP值,您可以創建一次並將其存儲在例如靜態或延遲初始化字段中。通過這種方式,你可以創建一個使用,如果沒有提供其他參數的默認值的方法:

void DoSomething(IEnumerable<MyRecord> records) 
{ 
    ... 
    //Set the TVP value 
    var tvpParam=sqlCommand.Parameters.Add("@SomeUDTArg",SqlDbType.Structured); 

    tvpParam.Value=(records==null)?DefaultValues:records.ToDataTable(); 

    //Run it 
    sqlCommand.ExecuteNonQuery(); 

    ... 

}