ADO.NET 高效调用存储过程
ADO.NET Call stored procedure efficiently
我有一个 存储过程,它在数据库 table 中有 inserts/updates 个条目。
我还有一个 Web 服务,需要每隔几秒 将大量新更新传递到数据库中。
我想在不对性能产生重大影响的情况下完成此操作,但是我不确定如何最好地解决这个问题。
这是我的代码(尽可能简化)
*注意:我使用数据table,因为存储过程使用的参数之一是自定义用户定义的table类型数据库。
public class DBWorker
{
public void Update(IEnumerable<UpdateModel> updates)
{
using (SqlConnection connection = new SqlConnection(this._connectionString))
using (SqlCommand command = new SqlCommand(this._storedProcedureString, connection) { CommandType = CommandType.StoredProcedure })
{
foreach (var update in updates)
{
command.Parameters.Add("@EntryID", SqlDbType.Int).Value = update.EntryID;
command.Parameters.Add("@Type", SqlDbType.Int).Value = update.Type;
DataTable dataTable = new DataTable();
dataTable.Columns.Add("ParamID");
dataTable.Columns.Add("Value");
DataRow row = dataTable.NewRow();
row["ParamID"] = update.ParamID;
row["Value"] = update.Value;
dataTable.Rows.Add(row);
command.Parameters.Add("@NameValues", SqlDbType.Structured).Value = dataTable;
command.ExecuteNonQuery();
}
}
}
}
public class UpdateModel
{
public int EntryID { get; set; }
public int Type { get; set; }
public int ParamID { get; set; }
public string Value { get; set; }
}
我主要担心的是,上面的代码将对每个更新进行查询,如果我有很多更新,将会大大减慢我的 DP。有什么方法可以在某些“bulk”模式下调用存储过程。
我正在考虑用我的所有结果创建一个数据table,然后以某种方式将其传递给存储过程,但我不确定这是否会带来实际的性能改进,也不知道如何实现实施它。
不确定这是否重要,但这是 SP 实际更新的 table 的结构:
- ID - 整数、身份、PK
- EntryID - 整数,非空
- 类型 - int,notnull
- ParamID - 整数,非空
- 值 - varchar,非空
你走的路是对的,但是...
- 您正在创建数据表,添加一行,并将数据表传递给存储过程。对于每个 UpdateModel。最好为每个更新创建一行(所有四列 - 来自更新对象的属性),然后将数据表(现在有很多行)传递给 SP。
- 考虑一下该命令发生了什么 - 特别是您将添加多少参数(假设您每次循环时都重新添加参数)。
- 为数据表中的列指定一些明确的数据类型
对于更新序列,比如 20,您想要一个包含 20 行、4 列的数据表,一个带有一个结构化参数的命令,并调用 SP 一次。
我有一个 存储过程,它在数据库 table 中有 inserts/updates 个条目。 我还有一个 Web 服务,需要每隔几秒 将大量新更新传递到数据库中。
我想在不对性能产生重大影响的情况下完成此操作,但是我不确定如何最好地解决这个问题。
这是我的代码(尽可能简化)
*注意:我使用数据table,因为存储过程使用的参数之一是自定义用户定义的table类型数据库。
public class DBWorker
{
public void Update(IEnumerable<UpdateModel> updates)
{
using (SqlConnection connection = new SqlConnection(this._connectionString))
using (SqlCommand command = new SqlCommand(this._storedProcedureString, connection) { CommandType = CommandType.StoredProcedure })
{
foreach (var update in updates)
{
command.Parameters.Add("@EntryID", SqlDbType.Int).Value = update.EntryID;
command.Parameters.Add("@Type", SqlDbType.Int).Value = update.Type;
DataTable dataTable = new DataTable();
dataTable.Columns.Add("ParamID");
dataTable.Columns.Add("Value");
DataRow row = dataTable.NewRow();
row["ParamID"] = update.ParamID;
row["Value"] = update.Value;
dataTable.Rows.Add(row);
command.Parameters.Add("@NameValues", SqlDbType.Structured).Value = dataTable;
command.ExecuteNonQuery();
}
}
}
}
public class UpdateModel
{
public int EntryID { get; set; }
public int Type { get; set; }
public int ParamID { get; set; }
public string Value { get; set; }
}
我主要担心的是,上面的代码将对每个更新进行查询,如果我有很多更新,将会大大减慢我的 DP。有什么方法可以在某些“bulk”模式下调用存储过程。
我正在考虑用我的所有结果创建一个数据table,然后以某种方式将其传递给存储过程,但我不确定这是否会带来实际的性能改进,也不知道如何实现实施它。
不确定这是否重要,但这是 SP 实际更新的 table 的结构:
- ID - 整数、身份、PK
- EntryID - 整数,非空
- 类型 - int,notnull
- ParamID - 整数,非空
- 值 - varchar,非空
你走的路是对的,但是...
- 您正在创建数据表,添加一行,并将数据表传递给存储过程。对于每个 UpdateModel。最好为每个更新创建一行(所有四列 - 来自更新对象的属性),然后将数据表(现在有很多行)传递给 SP。
- 考虑一下该命令发生了什么 - 特别是您将添加多少参数(假设您每次循环时都重新添加参数)。
- 为数据表中的列指定一些明确的数据类型
对于更新序列,比如 20,您想要一个包含 20 行、4 列的数据表,一个带有一个结构化参数的命令,并调用 SP 一次。