2017-05-30 52 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(); 

    ... 

}