将表值参数传递给具有不同字段数的存储过程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将表值参数传递给具有不同字段数的存储过程相关的知识,希望对你有一定的参考价值。
我有一个要求,我需要将表值参数传递给存储过程。客户端需要灵活地将字段添加到表值类型而不影响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).
答案
我最终动态生成数据表,如下所示:
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;
}
另一答案
您必须传递一个dataTable,其列数与数据库表列相同。
DataTable myDataTable = new DataTable("MyDataType");
myDataTable.Columns.Add("ID", typeof(Int32));
myDataTable.Columns.Add("Name ", typeof(string));
另一答案
第一步是通过查询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));
}
另一答案
首先得到数据表的结构(你的表类型)
DECLARE @ret yourTableName
SELECT * FROM @ret
然后在C#中填入您的数据并用它来调用您的存储过程
以上是关于将表值参数传递给具有不同字段数的存储过程的主要内容,如果未能解决你的问题,请参考以下文章