从存储过程中读取时不能使用CommandBehavior.KeyInfo" WITH RESULT SETS"

时间:2015-03-04 17:52:12

标签: c# .net sql-server

在SQL Server 2012或更高版本中运行以下命令

CREATE TABLE TestTable1
(
  Dim varchar(500),
  Measure money,
  PRIMARY KEY (Dim)
)
GO

CREATE TABLE TestTable2
(
  Dim varchar(500),
  Measure money,
  PRIMARY KEY (Dim)
)
GO

CREATE PROCEDURE [dbo].[usp_InnerSp]
(
       @Sql varchar(max)
)
AS
BEGIN
  EXEC(@sql)
END
GO

CREATE PROCEDURE [dbo].[usp_ParentSp]
AS
BEGIN
  DECLARE @sql VARCHAR(MAX);
  SET @sql = 'SELECT t1.* FROM TestTable1 t1 INNER JOIN TestTable2 t2 ON t1.Dim = t2.Dim'
  EXEC [dbo].[usp_InnerSp] @sql
  WITH RESULT SETS (
   (
    [Dim] VARCHAR(500),
    [Measure] MONEY
   )
  );
END
GO

在C#中创建一个控制台应用程序

static void Main(string[] args)
{
    using (SqlConnection connection = new SqlConnection(@"Data Source=.\SQL2014;Initial Catalog=AdventureWorksDW2012;Integrated Security=SSPI;"))
    {
        connection.Open();
        using (SqlCommand command = new SqlCommand("usp_ParentSp", connection))
        {
            command.CommandType = CommandType.StoredProcedure;
            using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo))
            {
            }
        }
    }
}

运行代码时,会出现以下System.Data.SqlClient.SqlException异常:

  

EXECUTE语句失败,因为其WITH RESULT SETS子句为结果集编号1指定了2个列,但该语句在运行时发送了3个列。

我希望.Net能够运行存储过程,即使它无论出于何种原因都无法检测到主键。

问题:你会推荐什么?这是.Net或SQL Server中的错误吗?

2 个答案:

答案 0 :(得分:3)

为什么在选择[Dim]列(CommandBehavior.KeyInfo)时甚至使用t1.*

要么根本不使用CommandBehavior.KeyInfo(最佳方法)。

或更改

WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY));

WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY, [PrimaryKey] VARCHAR(500)));

(最差的解决方案)。

或将t1.*更改为t1.Measure

WITH RESULT SETS (([Dim] VARCHAR(500), [Measure] MONEY));

WITH RESULT SETS (([Measure] MONEY, [PrimaryKey] VARCHAR(500)));

(优于2但仍然比1差)。

答案 1 :(得分:0)

为什么要使用WITH RESULT SETS开头?该错误与无法检测PK无关;它与添加到结果集的额外列有关,因为指定了CommandBehavior.KeyInfo,而SET NO_BROWSETABLE ON在执行查询之前又设置了SET NO_BROWSETABLE ON; EXEC dbo.usp_ParentSp; 。如果您运行,则SSMS中会出现相同的错误:

WITH RESULT SETS

因此该错误与.NET无关。

没有太多情况需要WITH RESULT SETS,并且显示的示例代码绝对不是其中之一,因此我建议从EXEC中删除SqlDataReader.GetSchemaTable()子句。并从WITH RESULT SETS获取结果集元数据。

此外,使用sys.dm_exec_describe_first_result_set无论如何都无济于事,因为它不支持使用动态SQL。您可以使用sp_describe_first_result_set,因为它可以使用动态SQL,但它还需要WITH RESULT SETS子句。当然,使用{{1}}最终并没有太大的好处,因为“is_part_of_unique_key”字段为NULL(至少在您的测试用例方面)。

相关问题