Har*_*rsh 5 c# ado.net multithreading sqlcommand
我有一个大约3000行的数据表.每个行都需要插入数据库表中.目前,我正在运行foreach循环,如下所示:
obj_AseCommand.CommandText = sql_proc;
obj_AseCommand.CommandType = CommandType.StoredProcedure;
obj_AseCommand.Connection = db_Conn;
obj_AseCommand.Connection.Open();
foreach (DataRow dr in dt.Rows)
{
obj_AseCommand.Parameters.AddWithValue("@a", dr["a"]);
obj_AseCommand.Parameters.AddWithValue("@b", dr["b"]);
obj_AseCommand.Parameters.AddWithValue("@c", dr["c"]);
obj_AseCommand.ExecuteNonQuery();
obj_AseCommand.Parameters.Clear();
}
obj_AseCommand.Connection.Close();
Run Code Online (Sandbox Code Playgroud)
您能否告诉我如何在数据库中并行执行SP,因为上述方法需要大约10分钟才能插入3000行.
编辑
事后看来,使用a Parallel.ForEach来并行化DB插入有点浪费,因为它也会为每个Connection消耗一个线程.可以说,更好的并行解决方案是使用System.DataDb操作的异步版本,例如ExecuteNonQueryAsync,启动执行(并发),然后使用await Task.WhenAll()等待完成 - 这将避免调用者的线程开销,尽管整体Db表现不会更快.更多这里
原始答案,多个并行插入数据库
您可以使用TPL并行执行此操作,例如,特别是与Parallel.ForEach的localInit重载.您几乎肯定希望通过调整MaxDegreeOfParalelism来限制并行数量,以便您不会淹没数据库:
Parallel.ForEach(dt.Rows,
// Adjust this for optimum throughput vs minimal impact to your other DB users
new ParallelOptions { MaxDegreeOfParallelism = 4 },
() =>
{
var con = new SqlConnection();
var cmd = con.CreateCommand();
cmd.CommandText = sql_proc;
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
cmd.Parameters.Add(new SqlParameter("@a", SqlDbType.Int));
// NB : Size sensitive parameters must have size
cmd.Parameters.Add(new SqlParameter("@b", SqlDbType.VarChar, 100));
cmd.Parameters.Add(new SqlParameter("@c", SqlDbType.Bit));
// Prepare won't help with SPROCs but can improve plan caching for adhoc sql
// cmd.Prepare();
return new {Conn = con, Cmd = cmd};
},
(dr, pls, localInit) =>
{
localInit.Cmd.Parameters["@a"] = dr["a"];
localInit.Cmd.Parameters["@b"] = dr["b"];
localInit.Cmd.Parameters["@c"] = dr["c"];
localInit.Cmd.ExecuteNonQuery();
return localInit;
},
(localInit) =>
{
localInit.Cmd.Dispose();
localInit.Conn.Dispose();
});
Run Code Online (Sandbox Code Playgroud)
笔记:
.Prepare()如果您在2005年之前使用AdHoc Sql或Sql版本,也可以考虑使用DataTable's是线程安全的.你当然想要仔细检查一下.边注:
即使使用宽桌和单线,3000行的10分钟也是过多的.你的过程做了什么?我假设处理不是微不足道的,因此需要SPROC,但是如果你只是做简单的插入,按照@ 3dd的注释,SqlBulkCopy将在一个相当窄的表上产生每分钟大约1M行的插入.
最好将整个数据表传递到数据库中
obj_AseCommand.CommandText = sql_proc;
obj_AseCommand.CommandType = CommandType.StoredProcedure;
obj_AseCommand.Connection = db_Conn;
obj_AseCommand.Connection.Open();
obj_AseCommand.Parameters.AddWithValue("@Parametername",DataTable);
obj_AseCommand.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)
在数据库中,您必须创建与您的数据表完全匹配的表类型
CREATE TYPE EmpType AS TABLE
(
ID INT, Name VARCHAR(3000), Address VARCHAR(8000), Operation SMALLINT //your columns
)
Run Code Online (Sandbox Code Playgroud)
在存储过程中,你可以做这样的事情......
create PROCEDURE demo
@Details EmpType READONLY // it must be read only
AS
BEGIN
insert into yourtable //insert data
select * from @Details
END
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15947 次 |
| 最近记录: |