使用Dapper删除超过2100行(通过ID)的正确方法

Vac*_*ano 10 sql-server parameters dapper

我正在尝试使用Dapper支持我的服务器应用程序的数据访问.

我的服务器应用程序有另一个应用程序,它以每分钟400的速度将记录丢入我的数据库.

我的应用程序将它们分批拉出,处理它们,然后从数据库中删除它们.

由于数据在我处理时继续流入数据库,因此我没有好的方法可以说delete from myTable where allProcessed = true.

但是,我确实知道要删除的行的PK值.所以我想做一个delete from myTable where Id in @listToDelete

问题是,如果我的服务器停机甚至6分钟,那么我有超过2100行要删除.

由于Dapper接受我的@listToDelete并将每个变成一个参数,我对delete的调用失败了.(导致我的数据清除进一步落后.)

在Dapper处理这个问题的最佳方法是什么?

注意:我已经查看了Tabled Valued Parameters,但从我所看到的情况来看,它们并不是非常高效.这段我的建筑是我系统的瓶颈,我需要非常快.

Chr*_*ith 14

一种选择是在服务器上创建临时表,然后使用批量加载工具立即将所有ID上载到该表中.然后使用join,EXISTS或IN子句仅删除上载到临时表中的记录.

批量加载是SQL Server中一个优化良好的路径,它应该非常快.

例如:

  1. 执行该语句 CREATE TABLE #RowsToDelete(ID INT PRIMARY KEY)
  2. 使用批量加载将密钥插入 #RowsToDelete
  3. 执行 DELETE FROM myTable where Id IN (SELECT ID FROM #RowsToDelete)
  4. 执行DROP TABLE #RowsToDelte(如果关闭会话,表也将自动删除)

(假设Dapper)代码示例:

conn.Open();

var columnName = "ID";

conn.Execute(string.Format("CREATE TABLE #{0}s({0} INT PRIMARY KEY)", columnName));

using (var bulkCopy = new SqlBulkCopy(conn))
{
    bulkCopy.BatchSize = ids.Count;
    bulkCopy.DestinationTableName = string.Format("#{0}s", columnName);

    var table = new DataTable();                    
    table.Columns.Add(columnName, typeof (int));
    bulkCopy.ColumnMappings.Add(columnName, columnName);

    foreach (var id in ids)
    {
        table.Rows.Add(id);
    }

    bulkCopy.WriteToServer(table);
}

//or do other things with your table instead of deleting here
conn.Execute(string.Format(@"DELETE FROM myTable where Id IN 
                                   (SELECT {0} FROM #{0}s", columnName));

conn.Execute(string.Format("DROP TABLE #{0}s", columnName));
Run Code Online (Sandbox Code Playgroud)


Vac*_*ano 5

为了让这段代码正常工作,我走到了黑暗的一边.

由于Dapper使我的列表成为参数.而SQL Server无法处理很多参数.(我以前从未需要双位数参数).我不得不使用Dynamic SQL.

所以这是我的解决方案:

string listOfIdsJoined = "("+String.Join(",", listOfIds.ToArray())+")";
connection.Execute("delete from myTable where Id in " + listOfIdsJoined);
Run Code Online (Sandbox Code Playgroud)

在每个人抓住他们的火把和干草叉之前,让我解释一下.

  • 此代码在服务器上运行,该服务器的唯一输入是来自Mainframe系统的数据馈送.
  • 我动态创建的列表是longs/bigint列表.
  • longs/bigint来自Identity列.

我知道构建动态SQL是坏juju,但在这种情况下,我只是看不出它如何导致安全风险.

  • @ Pure.Krome可能是他的`listOfIds`类型为`List <int>`因此无需清理输入 (3认同)