将表值参数传递给具有不同字段数的存储过程

时间:2015-02-24 22:51:29

标签: c# ado.net

我有一个要求,我需要将表值参数传递给存储过程。客户端需要灵活地将字段添加到表值类型而不影响C#代码(即使它需要删除并重新创建所有相关的存储过程)。是否可以向DataTable添加比数据类型更少的列? 我们正在使用Microsoft SQL Server 2008 R2。

我试过这个:

SQL:

CREATE TYPE [dbo].[MyDataType] As Table
(
    ID INT NULL,
    Name NVARCHAR(50) NULL
)

CREATE PROCEDURE [dbo].[MyProcedure]
(
    @myData As [dbo].[MyDataType] Readonly
)
AS
Begin
    Select * FROM @myData
End

C#:

DataTable myDataTable = new DataTable("MyDataType");
myDataTable.Columns.Add("Id", typeof(Int32));
myDataTable.Rows.Add(1);
myDataTable.Rows.Add(2);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@myData";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = myDataTable;
command.Parameters.Add(parameter); 

我遇到以下异常:

A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Trying to pass a table-valued parameter with 1 column(s) where the corresponding user-defined table type requires 2 column(s).

4 个答案:

答案 0 :(得分:1)

我最终动态生成数据表如下:

   public static DataTable GetDataTableFromSchema(string userDefinedTableTypeName, SqlConnection connection)
    {
        var query = "SELECT SC.name, ST.name AS datatype FROM sys.columns SC " +
                    "INNER JOIN sys.types ST ON ST.system_type_id = SC.system_type_id AND ST.is_user_defined = 0 " +
                    "WHERE SC.object_id = " +
                    "   (SELECT type_table_object_id FROM sys.table_types WHERE name = '" + userDefinedTableTypeName + "');";

        var dataTable = new DataTable();

        using (var command = new SqlCommand(query, connection))
        {
            using (var sqlDataReader = command.ExecuteReader())
            {
                while (sqlDataReader.Read())
                {
                    var columnName = sqlDataReader["name"].ToString();
                    var sqlDbType = (SqlDbType) Enum.Parse(typeof (SqlDbType), sqlDataReader["datatype"].ToString(), true);
                    var clrType = GetClrType(sqlDbType);
                    dataTable.Columns.Add(columnName, clrType);
                }
            }                
        }


        return dataTable;
    }

答案 1 :(得分:0)

您必须传递一个dataTable,其列数与数据库表列相同。

DataTable myDataTable = new DataTable("MyDataType");
myDataTable.Columns.Add("ID", typeof(Int32));
myDataTable.Columns.Add("Name ", typeof(string));

答案 2 :(得分:0)

第一步是通过查询dataBase.INFORMATION_SCHEMA来执行查询以获取列的名称和类型。

SELECT COLUMN_NAME,DATA_TYPE 
FROM yourDataBase.INFORMATION_SCHEMA.COLUMNS
WHERE  TABLE_NAME = 'yourTableName'

第二步是在循环语句中使用此结果来构建您将其作为参数发送的所需dataTable

Foreach (var item in ColumnsNameType)
{
   myDataTable.Columns.Add(item.COLUMN_NAME, typeof(item.COLUMN_NAME));
}

答案 3 :(得分:0)

首先获取数据表的结构(您的表类型)

DECLARE @ret yourTableName
SELECT * FROM @ret

然后在C#中用您的数据填充它,并将其用于调用存储过程

相关问题