Mar*_*acz 162 c# sql-server stored-procedures sqlcommand table-valued-parameters
我有一个MS SQL Server 2005数据库.在一些过程中,我将表参数作为nvarchar(以逗号分隔)传递给存储过程,并在内部划分为单个值.我将它添加到SQL命令参数列表中,如下所示:
cmd.Parameters.Add("@Logins", SqlDbType.NVarchar).Value = "jim18,jenny1975,cosmo";
Run Code Online (Sandbox Code Playgroud)
我必须将数据库迁移到SQL Server 2008.我知道有表值参数,我知道如何在存储过程中使用它们.但我不知道如何将一个传递给SQL命令中的参数列表.有谁知道Parameters.Add程序的正确语法?或者是否有另一种传递此参数的方法?
Rya*_*hel 265
DataTable,DbDataReader或IEnumerable<SqlDataRecord>对象可用于根据SQL Server 2008(ADO.NET)中的MSDN文章表值参数填充表值参数.
以下示例说明使用a DataTable或IEnumerable<SqlDataRecord>:
SQL代码:
CREATE TABLE dbo.PageView
(
PageViewID BIGINT NOT NULL CONSTRAINT pkPageView PRIMARY KEY CLUSTERED,
PageViewCount BIGINT NOT NULL
);
CREATE TYPE dbo.PageViewTableType AS TABLE
(
PageViewID BIGINT NOT NULL
);
CREATE PROCEDURE dbo.procMergePageView
@Display dbo.PageViewTableType READONLY
AS
BEGIN
MERGE INTO dbo.PageView AS T
USING @Display AS S
ON T.PageViewID = S.PageViewID
WHEN MATCHED THEN UPDATE SET T.PageViewCount = T.PageViewCount + 1
WHEN NOT MATCHED THEN INSERT VALUES(S.PageViewID, 1);
END
Run Code Online (Sandbox Code Playgroud)
C#代码:
private static void ExecuteProcedure(bool useDataTable,
string connectionString,
IEnumerable<long> ids)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "dbo.procMergePageView";
command.CommandType = CommandType.StoredProcedure;
SqlParameter parameter;
if (useDataTable) {
parameter = command.Parameters
.AddWithValue("@Display", CreateDataTable(ids));
}
else
{
parameter = command.Parameters
.AddWithValue("@Display", CreateSqlDataRecords(ids));
}
parameter.SqlDbType = SqlDbType.Structured;
parameter.TypeName = "dbo.PageViewTableType";
command.ExecuteNonQuery();
}
}
}
private static DataTable CreateDataTable(IEnumerable<long> ids)
{
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(long));
foreach (long id in ids)
{
table.Rows.Add(id);
}
return table;
}
private static IEnumerable<SqlDataRecord> CreateSqlDataRecords(IEnumerable<long> ids)
{
SqlMetaData[] metaData = new SqlMetaData[1];
metaData[0] = new SqlMetaData("ID", SqlDbType.BigInt);
SqlDataRecord record = new SqlDataRecord(metaData);
foreach (long id in ids)
{
record.SetInt64(0, id);
yield return record;
}
}
Run Code Online (Sandbox Code Playgroud)
Sco*_*NET 30
继瑞安的回答,你也将需要设置DataColumn的Ordinal,如果你正在处理一个属性table-valued parameter与多列,其序号是不按字母顺序排列.
例如,如果您具有以下用作SQL中参数的表值:
CREATE TYPE NodeFilter AS TABLE (
ID int not null
Code nvarchar(10) not null,
);
Run Code Online (Sandbox Code Playgroud)
您需要在C#中按顺序排序列:
table.Columns["ID"].SetOrdinal(0);
// this also bumps Code to ordinal of 1
// if you have more than 2 cols then you would need to set more ordinals
Run Code Online (Sandbox Code Playgroud)
如果你没有这样做,你将得到一个解析错误,无法将nvarchar转换为int.
Mar*_*tea 14
通用
public static DataTable ToTableValuedParameter<T, TProperty>(this IEnumerable<T> list, Func<T, TProperty> selector)
{
var tbl = new DataTable();
tbl.Columns.Add("Id", typeof(T));
foreach (var item in list)
{
tbl.Rows.Add(selector.Invoke(item));
}
return tbl;
}
Run Code Online (Sandbox Code Playgroud)
最干净的方式.假设您的表是一个名为"dbo.tvp_Int"的整数列表(自定义为您自己的表类型)
创建此扩展方法......
public static void AddWithValue_Tvp_Int(this SqlParameterCollection paramCollection, string parameterName, List<int> data)
{
if(paramCollection != null)
{
var p = paramCollection.Add(parameterName, SqlDbType.Structured);
p.TypeName = "dbo.tvp_Int";
DataTable _dt = new DataTable() {Columns = {"Value"}};
data.ForEach(value => _dt.Rows.Add(value));
p.Value = _dt;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您只需执行以下操作即可在任意位置添加一个表值参数:
cmd.Parameters.AddWithValueFor_Tvp_Int("@IDValues", listOfIds);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
256629 次 |
| 最近记录: |