Dapper는 왜 미니 프로파일 러 연결이 있거나없는 다른 SQL을 생성합니까?

dapper mvcminiprofiler mvc-mini-profiler npgsql

문제

Dapper (1.13 Noobget Package)는 일반 ADO.NET 데이터베이스 연결 또는 데코 레이팅 된 미니 프로파일 러 데이터베이스 연결과 함께 사용되는지에 따라 다른 SQL 문을 생성합니다.

예제 코드 (Postgresql로 테스트 됨)

용도 :

using System.Linq;
using Dapper;
using Npgsql;
using NUnit.Framework;
using StackExchange.Profiling;
using StackExchange.Profiling.Data;

Test1은 일반 ADO.NET 연결을 사용하고 실패합니다 .

[TestFixture]
public class DapperTests {
  private const string cnnstr = "HOST=...;DATABASE=...;USER ID=...;PASSWORD=...;";

  [Test]
  public void Test1() {
    using (var cnn = new NpgsqlConnection(cnnstr)) {
      cnn.Open();

      // The following line fails:
      cnn.Query<int>("SELECT 1 WHERE 42 IN @Items", new {Items = new[] {41, 42, 43}}).Single();

      // Npgsql.NpgsqlException : ERROR: 42883: operator does not exist: integer = integer[]
    }
  }

Test2는 ADO.NET 연결을 감싸는 미니 프로파일 러 연결을 사용하고 성공합니다 .

  [Test]
  public void Test2() {
    using (var cnn = new NpgsqlConnection(cnnstr))
    using (var profiled = new ProfiledDbConnection(cnn, MiniProfiler.Start())) {
      profiled.Open();

      int result = profiled.Query<int>("SELECT 1 WHERE 42 IN @Items", new {Items = new[] {41, 42, 43}}).Single();

      Assert.AreEqual(1, result);
    }
  }
}

생성 된 SQL을 보면 Test1이 실패한 이유가 분명해진다.

  • Test1의 SQL : SELECT 1 WHERE 42 IN ( (array [41,42,43]) :: int4 [] )
  • Test2의 SQL : SELECT 1 WHERE 42 IN (((41)), ((42)), ((43)))

배열은 IN을 지원하지 않습니다.

왜 dapper는 프로파일 링 된 연결과 함께 사용되거나 연결없이 사용되는 경우 서로 다른 SQL을 생성합니까?

일반 연결로 배열 [...]을 생성하는 이유는 무엇입니까? dapper의 문서 덕분에 튜플을 생성해야합니다.

대퍼 목록 지원

인기 답변

Dapper에는 배열의 특수 처리를위한 설정을 포함하는 "FeatureSupport"클래스가 있습니다. Postgresql 연결은 배열을 지원하도록 표시되어 있지만 다른 연결 유형 ( MiniProfiler ProfiledDbConnections 포함 )은 배열을 지원하지 않는 것으로 표시되어 있습니다.

연결이 배열을 지원하지 않으면 Dapper는 (docs에서 설명한 것처럼) 배열의 각 항목에 대해 하나의 매개 변수를 수동으로 만듭니다. SELECT 1 WHERE 42 IN (41,42,43)

연결이 Postgres의 NpgsqlConnection과 같은 배열을 지원하면 배열 매개 변수가 연결에 직접 전달되어 다음과 같이 추악한 결과가 발생합니다. SELECT 1 WHERE 42 IN ( '{41,42,43}':: int4 [] ) - IN은 배열을 지원하지 않기 때문에 실제로는 실패합니다.

관련 코드는 SqlMapper.PackListParameters 메서드에 있습니다.

따라서 ProfiledDbConnections와 NpgsqlConnections를 전환하면 생성 된 SQL이 달라 지므로 문제가 발생합니다.

Postgres 연결에서 배열 구문을 없애려면 다음 코드를 사용할 수 있습니다 (전역 수준에서만 작동하지만 ...).

using Dapper;
using Npgsql;

using (var cnn = new NpgsqlConnection())
  FeatureSupport.Get(cnn).Arrays = false;

쿼리 별 또는 매개 변수 별 배열 구문을 활성화 / 비활성화하는 방법이없는 것 같습니다.

추신 : https://code.google.com/p/dapper-dot-net/issues/detail?id=107&q=postgres 에서이 문제에 대한 문제를 발견했습니다.



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