2013-12-19 2 views
2

Вызов proc из C# (.NET 4.5, Visual Studio 2013), он передает переменные таблицы, используя sp_executesql. Однако SQL Server (протестированный в 2008 Std, 2008 Ent и 2012 Std) проходит через пустую таблицу.Передача переменной таблицы с C# на SQL Server проходит пустую таблицу

Я бы ожидал, что три утверждения здесь возвратят те же результаты, но последний не будет.

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[_testproc]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[_testproc] 
GO 

IF EXISTS (SELECT * FROM sys.types st JOIN sys.schemas ss ON st.schema_id = ss.schema_id WHERE st.name = N'testType' AND ss.name = N'dbo') 
DROP TYPE [dbo].[testType] 
GO 
-------------------------------- 
CREATE TYPE [dbo].[testType] AS TABLE(
    [ServerID] [int] NULL 
    , [Field2] int NOT NULL 
) 

GO 
--------------------------------- 
CREATE PROC _testproc 
    @testTable testType READONLY 
AS 

SELECT * FROM @testTable 

GO 
--------------------------------- 
declare @x testtype 

INSERT INTO @X values (1,2) 
INSERT INTO @X values (3,4) 

--Begin Three calls that should return the same result 
--Query the table directly 
SELECT * FROM @x 

--Call it the way I would through t-sql 
exec _testproc @testTable = @x 

--Call it the way C# in Visual Studio 2013 calls it 
exec sp_executesql N'dbo._testproc',N'@testTable [dbo].[TestType] READONLY',@[email protected] 

--Cleanup 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[_testproc]') AND type in (N'P', N'PC')) 
DROP PROCEDURE [dbo].[_testproc] 
GO 

IF EXISTS (SELECT * FROM sys.types st JOIN sys.schemas ss ON st.schema_id = ss.schema_id WHERE st.name = N'testType' AND ss.name = N'dbo') 
DROP TYPE [dbo].[testType] 
GO 

Очевидным ответом мне было бы не использовать sp_executesql со столом переменных в прок, но это C# код делает именно это.

using (SqlCommand cmd = new SqlCommand("dbo._testproc", connCentral)) 
      { 
       SqlParameter sqlpTestTable = cmd.Parameters.AddWithValue("@TestTable", dtTestTable); 
       sqlpTestTable.SqlDbType = SqlDbType.Structured; 
       sqlpTestTable.TypeName = "dbo.TestType"; 

       using (SqlDataAdapter aTest = new SqlDataAdapter()) 
       { 
        aTest.SelectCommand = cmd; 

        aTest.Fill(dsTest2, "Test2"); 
       } 
      } 

Любая помощь, которую вы можете мне дать, была бы весьма признательна. Благодаря!!!

ответ

1

Изменить ...

exec sp_executesql N'dbo._testproc',N'@testTable [dbo].[TestType] READONLY',@[email protected] 

К ...

exec sp_executesql N'dbo._testproc @testTable',N'@testTable [dbo].[TestType] READONLY',@[email protected] 

Я проверил, он работает. Вы передаете переменную в текст выполненной команды, но вы не используете эту переменную в тексте команды.

+1

Это работает как с SQL Server, так и с .NET, и спасибо. Однако я бы добавил, что это не так, как вы обычно передаете параметры из кода .NET. На данный момент мне кажется, что я использую обходное решение вместо правильного кода, хотя я очень рад этому! используя (SqlCommand cmd = новый SqlCommand ("dbo._testproc @testTable", connCentral)) –