所以这个问题才刚刚开始出现在分析器中。
我们有一些看起来像这样的东西。
using (var cmd = connection.CreateCommand()) {
cmd.CommandText = "INSERT INTO #Ids VALUES (@0);";
cmd.Parameters.Add(cmd.CreateParameter() { ParameterName = "@0", DbType = DbType.Integer });
cmd.Prepare();
foreach (var value in values)
{
((IDbDataParameter)cmd.Parameters[0]).Value = value;
cmd.ExecuteNonQuery();
}
}
我们正在研究通过减少往返次数来加快这一速度的可能性。在这里使用 DataTable 会是一个怪物,但有一种类型
SqlDataRecord
似乎很合适,所以我们应该能够做这样的事情:
using (var cmd = connection.CreateCommand()) {
cmd.CommandText = "INSERT INTO #Ids SELECT * FROM @0;";
var param = cmd.CreateParameter();
param.ParameterName = "@0";
// FIXME more properties
cmd.Parameters.Add(param);
param.Value = values.Cast<int>().Select((x) => {
// FIXME Create new SqlDataRecord
}.ToList();
cmd.ExecuteNonQuery();
}
我在哪里找不到 API 的示例,也不知道如何使用它。由于 SqlClient 中的类型无意义,普通的 Visual Studio Intellisense 是无用的。
如何填写上面的 FIXME 注释?
相关问题,没有好的答案:当我有一大堆 ID 时,如何在 SQL Server 中创建临时表
评论中有人要求了解更大的情况。确实没有一个很好的方法可以通过缩小这里来获取更多信息。代码库中只有一份例程为所有 SQL 调用(即存储过程)设置参数,就是这个。
行数的比例因子是肥尾的;平均行数小于 10,但最大大小非常大,并且经常发生超过 1000 行的调用。因此我们加载一个临时表;在转换为执行
foreach
循环以外的操作时,我们仍然加载临时表。
明天我需要检查如何从.net代码将表值参数传递到存储过程是否是一个有效的欺骗目标。
一个完整的工作示例。
using var connection = new SqlConnection(@"...");
connection.Open();
int[] values = [1, 2, 3, 4, 5];
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "CREATE TYPE dbo.Ids AS TABLE (Id INT );";
cmd.ExecuteNonQuery();
}
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "CREATE TABLE #Ids (Id INT);";
cmd.ExecuteNonQuery();
}
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "INSERT INTO #Ids SELECT * FROM @0;";
var param = cmd.CreateParameter();
param.ParameterName = "@0";
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "dbo.Ids";
cmd.Parameters.Add(param);
var record = new SqlDataRecord(new SqlMetaData("Id", SqlDbType.Int));
param.Value = values.Cast<int>()
.Select(x =>
{
//var record = new SqlDataRecord(new SqlMetaData("Id", SqlDbType.Int));
record.SetInt32(0, x);
return record;
})
//.ToList()
;
var affectedRows = cmd.ExecuteNonQuery();
Console.WriteLine($"Rows inserted: {affectedRows}");
}
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = "SELECT COUNT(*) FROM #Ids;";
var count = cmd.ExecuteScalar();
Console.WriteLine($"Count: {count}");
}