sourcecode

Dapper ORM을 사용하여 * FROM X WHERE ID IN (...)를 선택합니다.

copyscript 2023. 4. 14. 22:00
반응형

Dapper ORM을 사용하여 * FROM X WHERE ID IN (...)를 선택합니다.

비즈니스 로직에서 IN 절의 값 목록을 가져올 때 Dapper ORM을 사용하여 IN 절을 사용하여 쿼리를 작성하는 가장 좋은 방법은 무엇입니까?예를 들어 다음과 같은 질문이 있다고 가정합니다.

SELECT * 
  FROM SomeTable 
 WHERE id IN (commaSeparatedListOfIDs)

commaSeparatedListOfIDs비즈니스 로직에서 전달되고 있으며, 이는 어떤 유형의 데이터도 될 수 있습니다.IEnumerable(of Integer)이 경우 쿼리를 어떻게 구성해야 합니까?지금까지 해 온 스트링 접속을 해야 하나요?아니면 제가 모르는 고급 파라미터 매핑 기술이 있나요?

Dapper는 이를 직접 지원합니다.예를 들면...

string sql = "SELECT * FROM SomeTable WHERE id IN @ids"
var results = conn.Query(sql, new { ids = new[] { 1, 2, 3, 4, 5 }});

Postgres를 사용하지 않는 한 다음 답변을 참조하십시오.

GitHub 프로젝트 홈페이지에서 직접 :

Dapper를 사용하면 IEnumerable로 전달하고 쿼리를 자동으로 파라미터화할 수 있습니다.

connection.Query<int>(
    @"select * 
      from (select 1 as Id union all select 2 union all select 3) as X 
      where Id in @Ids", 
    new { Ids = new int[] { 1, 2, 3 });

번역처:

select * 
from (select 1 as Id union all select 2 union all select 3) as X 
where Id in (@Ids1, @Ids2, @Ids3)

// @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3

만약 당신이IN절이 너무 커서 MSQL에서 처리할 수 없습니다. 테이블 값 매개 변수를 대퍼와 함께 사용하면 매우 쉽게 사용할 수 있습니다.

  1. MSSQL에서 TVP 유형을 만듭니다.

    CREATE TYPE [dbo].[MyTVP] AS TABLE([ProviderId] [int] NOT NULL)
    
  2. 작성하다DataTableTVP와 같은 컬럼을 사용하여 값을 입력합니다.

    var tvpTable = new DataTable();
    tvpTable.Columns.Add(new DataColumn("ProviderId", typeof(int)));
    // fill the data table however you wish
    
  3. Dapper 쿼리를 수정하여INNER JOINTVP 테이블:

    var query = @"SELECT * FROM Providers P
        INNER JOIN @tvp t ON p.ProviderId = t.ProviderId";
    
  4. Dapper 쿼리 호출로 DataTable을 전달합니다.

    sqlConn.Query(query, new {tvp = tvpTable.AsTableValuedParameter("dbo.MyTVP")});
    

이것은 여러 컬럼의 대량 갱신을 하고 싶을 때도 훌륭하게 동작합니다.TVP를 구축해, 그 후,UPDATETVP에 이너 조인을 하고 있습니다.

포스트그레스 예시:

string sql = "SELECT * FROM SomeTable WHERE id = ANY(@ids)"
var results = conn.Query(sql, new { ids = new[] { 1, 2, 3, 4, 5 }});

또한 다음과 같이 쿼리 문자열에 괄호를 둘러 싸지 마십시오.

SELECT Name from [USER] WHERE [UserId] in (@ids)

Dapper 1.50.2를 사용하여 SQL 구문 오류를 발생시켰으며 괄호를 삭제하여 수정했습니다.

SELECT Name from [USER] WHERE [UserId] in @ids

ID 목록을 사용하여 Dapper에서 많은 행을 쿼리하는 가장 빠른 방법은 다음과 같습니다.이것은 생각할 수 있는 거의 다른 방법보다 빠릅니다(다른 답변에 나와 있는 TVP를 사용하는 경우를 제외하고 테스트하지 않았습니다만, 아직 TVP를 장착해야 하기 때문에 속도가 느릴 수 있습니다).Dapper보다 빠른 행성입니다.IN엔티티 프레임워크보다 구문 및 유니버스가 더 빠릅니다.그리고 그것은 심지어 대륙의 목록을 통과하는 것보다 더 빠르다.VALUES또는UNION ALL SELECT여러 개의 열 키를 사용하기 위해 쉽게 확장할 수 있습니다. 추가 열을 추가하기만 하면 됩니다.DataTable 및 conditions , " " " " " " " 입니다.

public IReadOnlyCollection<Item> GetItemsByItemIds(IEnumerable<int> items) {
   var itemList = new HashSet(items);
   if (itemList.Count == 0) { return Enumerable.Empty<Item>().ToList().AsReadOnly(); }

   var itemDataTable = new DataTable();
   itemDataTable.Columns.Add("ItemId", typeof(int));
   itemList.ForEach(itemid => itemDataTable.Rows.Add(itemid));

   using (SqlConnection conn = GetConnection()) // however you get a connection
   using (var transaction = conn.BeginTransaction()) {
      conn.Execute(
         "CREATE TABLE #Items (ItemId int NOT NULL PRIMARY KEY CLUSTERED);",
         transaction: transaction
      );

      new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction) {
         DestinationTableName = "#Items",
         BulkCopyTimeout = 3600 // ridiculously large
      }
         .WriteToServer(itemDataTable);
      var result = conn
         .Query<Item>(@"
            SELECT i.ItemId, i.ItemName
            FROM #Items x INNER JOIN dbo.Items i ON x.ItemId = i.ItemId
            DROP TABLE #Items;",
            transaction: transaction,
            commandTimeout: 3600
         )
         .ToList()
         .AsReadOnly();
      transaction.Rollback(); // Or commit if you like
      return result;
   }
}

대량 삽입에 대해 조금 배워야 합니다.트리거 발생(기본값은 no), 제약 조건 준수, 테이블 잠금, 동시 삽입 허용 등의 옵션이 있습니다.

추가할 필요가 없습니다.()WHERE 절에 포함시킵니다., 여기 있습니다.syntax:-

const string SQL = "SELECT IntegerColumn, StringColumn FROM SomeTable WHERE IntegerColumn IN @listOfIntegers";

var conditions = new { listOfIntegers };
    
var results = connection.Query(SQL, conditions);

제 경우, 저는 다음과 같은 것을 사용했습니다.

var query = "select * from table where Id IN @Ids";
var result = conn.Query<MyEntity>(query, new { Ids = ids });

두 번째 줄의 변수 "ids"는 IEnumberable 문자열이며 정수일 수도 있습니다.

제 경험상 가장 친근한 방법은 문자열을 가치의 표로 변환하는 함수를 갖는 것입니다.

웹에서는 많은 스플리터 기능을 이용할 수 있습니다.SQL의 플레이버에 관계없이 쉽게 찾을 수 있습니다.

그러면...

SELECT * FROM table WHERE id IN (SELECT id FROM split(@list_of_ids))

또는

SELECT * FROM table INNER JOIN (SELECT id FROM split(@list_of_ids)) AS list ON list.id = table.id

(또는 유사)

SELECT * FROM tbl WHERE col IN @val

, 이 은, 「 」, 「 」, 「 」, 「 」와 같이 하지 않는 을 알 수 .byte[]로 랩해야 . Dapper는 마지막 요소만 사용하며 매개 변수는 상위 항목으로 묶어야 합니다.을 「」로 하면, 「」가 됩니다.int[]모든 것이 잘 된다.

포스트그레용SQL, 문자열 보간은 에서 도움이 된다는 것을 알게 되었습니다.그물.

예:

var ids = new int[] { 1, 2, 3 };
var query = "SELECT name FROM table WHERE id IN ({string.Join(",", ids)})";
using var connection = _dapperContext.CreateConnection();
var results = await connection.QueryAsync<ResultModel>(query);

언급URL : https://stackoverflow.com/questions/8388093/select-from-x-where-id-in-with-dapper-orm

반응형