Dapper를 사용하여 2100 개가 넘는 행 (ID 별)을 삭제하는 올바른 방법

dapper parameters sql-server

문제

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를 살펴 봤지만 볼 수있는 것에서는별로 성과 가 없습니다. 이 건축물은 제 시스템의 병목 목이며 매우 빨라야합니다.

수락 된 답변

한 가지 옵션은 서버에 임시 테이블을 만든 다음 대량로드 기능을 사용하여 모든 ID를 한 번에 해당 테이블에 업로드하는 것입니다. 그런 다음 조인, 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) 실행 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));

인기 답변

이 코드를 작동 시키려면 어두운면을 보았습니다.

Dapper가 내 목록을 매개 변수로 만드므로. 그리고 SQL Server는 많은 매개 변수를 처리 할 수 ​​없습니다. (필자는 두 자리 숫자의 매개 변수조차도 필요로하지 않았다.) 동적 SQL을 사용해야했습니다.

그래서 여기 내 해결책이있다.

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

모든 사람들이 횃불과 갈퀴를 잡기 전에 설명해 드리겠습니다.

  • 이 코드는 입력 만이 메인 프레임 시스템의 데이터 피드 인 서버에서 실행됩니다.
  • 내가 동적으로 만드는 목록은 longs / bigints의 목록입니다.
  • longs / bigint는 Identity 열에 있습니다.

역동적 인 SQL을 구축하는 것이 나쁜 주주라는 것을 알고 있지만이 경우 어떻게 보안 위험에 빠지는 지 알 수 없습니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.