如何在C#中执行表SP

时间:2009-06-16 15:31:59

标签: c# sql user-defined-types

我查看了SQLTeam网站,但现在遇到了一个新问题,因为我有一个IDENTITY列而他们的示例没有。

我有SQL Server 2008和VS 2008.我正在尝试使用C#和表UDT执行InsertPIF SP,但是我得到了一个异常。我查看了一个SQLTeam网站 使用表UDT的示例,但它们的示例没有像我一样的标识列。

但是,他们的示例表没有像我这样的标识列。 我想做的应该是简单的。我尝试了很多不同的变体,但基本上是:

ALTER PROCEDURE [dbo].[InsertPIF] @InputFileParam parseInputFile READONLY
AS
INSERT dbo.ParentTable SELECT strRow FROM @InputFileParam
GO

,其中

CREATE TABLE [dbo].[ParentTable](
    [ParentID] [int] IDENTITY(1,1) NOT NULL,
    [strInput] [varchar](8000) NULL,
PRIMARY KEY NONCLUSTERED 
(...)

并输入:

CREATE TYPE [dbo].[parseInputFile] AS TABLE(
    [NumCols] [int] IDENTITY(1,1) NOT NULL,
    [strRow] [varchar](500) NOT NULL,
    PRIMARY KEY CLUSTERED 
(...)

我要做的是执行上面的SP以将新记录插入ParentTable。例如:

INSERT INTO ParentTable(strInput) VALUES ('A3|BB|C|DDD')
INSERT INTO ParentTable(strInput) VALUES ('A4|GOB|BLDY|GOOK')
INSERT INTO ParentTable(strInput) VALUES ('A5|Hello|My|Darling')

以下是AppendData部分之前的更多C#代码:

DataTable dt = new DataTable();
String[] header = myStringArray[0].Split('|');

DataRow dr = dt.NewRow();
DataColumn dc = new DataColumn();
dc.DataType = typeof(Int32);
dc.ColumnName = “NumCols”;
dc.AutoIncrement=true;
dt.Columns.Add(dc);

DataColumn dc2 = new DataColumn();
dc2.DataType = typeof(string);
dc2.ColumnName = “strRow”;
dt.Columns.Add(dc2);
dr["NumCols"] = 1;
dr["strRow"] = "AA|BBB|CC|DD|E";
dt.Rows.Add(dr);

...
                SqlConnection conn = new SqlConnection(connString);
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "dbo.InsertPIF";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Connection = conn;
                SqlParameter param = cmd.Parameters.AddWithValue("@InputFileParam", SqlDbType.Structured);

        param.Value = dt;
        conn.Open();
        RowsAffected = cmd.ExecuteNonQuery();

我为ParentTable设置了身份,但似乎我必须在每个会话中执行此操作,所以我不确定如何删除身份要求或者让身份保持打开状态。例外:

INSERT到表变量上不允许的标识列。表值参数'@InputFileParam'的数据不符合参数的表类型。

如何执行此SP?

3 个答案:

答案 0 :(得分:1)

好吧,我还没有真正使用过TVP,所以我可能错了 - 但是从我的阅读中可以看出,&一般的SS背景,我认为你的问题是:

您的永久表具有标识列,因此SS希望为您处理。你可以设置身份插入,但这不是一个好主意......

要尝试的一件事是指定要在SP中插入的列:

ALTER PROCEDURE [dbo].[InsertPIF] @InputFileParam parseInputFile READONLY
AS
INSERT dbo.ParentTable (strInput) SELECT strRow FROM @InputFileParam
GO
另一件要看的事情,正如Tim Lentine建议的那样(在我写这个答案的时候),无论你是否真的到了服务器。由于您已将DataTable中的NumCols列定义为AutoIncrement,因此可能是您在C#代码中获得异常,位于:

...
dr["NumCols"] = 1;
...

<编辑>

当我点击提交时,不知道我在做什么......

如果是这种情况,请在创建DataTable时尝试省略AutoIncrement。如果列数据类型是一致的,那么在将TVP排列为与SS类型“相同”时,此属性无关紧要。

< /编辑>

答案 1 :(得分:1)

我认为Roland走在正确的轨道上 - IDENTITY专栏肯定是问题所在。由于您的最终目标表已经有一个IDENTITY列,它将自动为您填充,我建议不要在用户定义的表类型中指定相同的列(并且也不要在表类型上声明主键):

CREATE TYPE [dbo].[parseInputFile] AS TABLE
    ([strRow] [varchar](500) NOT NULL)

然后在您的C#代码中,只需设置一个包含单列的DataTable:

DataTable dt = new DataTable();

DataColumn dc = new DataColumn();
dc.DataType = typeof(string);
dc.ColumnName = “strRow”;
dt.Columns.Add(dc);

然后将您的列添加到DataTable“dt” - 只有一个字符串“strRow”。

在存储过程中,然后使用用户定义的表类型调用,只需插入字符串:

ALTER PROCEDURE [dbo].[InsertPIF] @InputFileParam parseInputFile READONLY
AS
  INSERT INTO dbo.ParentTable(strInput)
    SELECT strRow FROM @InputFileParam
GO

应该这样做,我希望! (我没有时间自己测试一下)

马克

答案 2 :(得分:0)

该错误是否可能来自parseInputFile表? NumCols被定义为标识字段,但在C#代码中,您将记录的值设置为1.