2013-12-19 1 views
2

C# (.NET 4.5, Visual Studio 2013)에서 proc를 호출하면 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 

나에게 확실한 대답은 PROC 테이블 변수를 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 코드에서 매개 변수를 전달하는 방법이 아닙니다. 이 시점에서 적절한 코드 대신 해결 방법을 사용하고있는 것처럼 느껴진다. 비록이 코드를 가지고 매우 행복하다. using (SqlCommand cmd = 새 SqlCommand ("dbo._testproc @testTable", connCentral)) –