여러 값 삽입 및 여러 값 반환

c# dapper postgresql sql

문제

나는 Dapper를 사용하기 시작했고 다음과 같은 문제에 봉착했습니다.

일련의 레코드를 삽입하고 삽입 된 레코드를 자동 증가 된 ID와 함께 반환하려고합니다.

Postgres를 사용하여이 쿼리와 같은 것을 실행하고 싶습니다 :

INSERT INTO players (name) 
VALUES ('Player1'), ('Player2'), ('Player3'), ('Player4'), ('Player5')
RETURNING id, name;

Dapper를 사용하여 플레이어 목록에서이 쿼리를 실행하고 플레이어 목록으로 다시 연결합니다 (ID를 사용하여).이 작업을 수행 할 수 있다고 생각했습니다.

public class Player
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var players = new List<Player> { new Player { Name = "Player1" }, new Player { Name = "Player2" }, new Player { Name = "Player3" }, new Player { Name = "Player4" }, new Player { Name = "Player5" }}

connection.Query<Player>("INSERT INTO players (name) VALUES (@Name) \r\n" + 
    "RETURNING id, name, tag;", 
    players);

그러면 다음 오류가 발생합니다 (이름이있는 플레이어 목록).

Parameter '@Name' referenced in SQL but not found in parameter list

Query ()는 매개 변수 목록을 지원하지 않을 수도 있으므로 connect.Execute ()를 대신 시도했습니다. Execute는 작동하지만 분명히 삽입 된 플레이어를 ID로 돌려 보내지 않습니다.

하나의 값을 삽입 할 때 INSERT와 RETURNING을 할 수 있다는 점은 주목할 가치가 있습니다.

누구도 내가 어떻게 Dapper와 같은 여러 값에 대해 INSERT 및 RETURNING을 할 수 있는지 알고 있습니까?

최신 정보

나는이 (다소 더러운) 해결책을 가지고있다 :

        var sb = new StringBuilder();
        sb.Append("INSERT INTO players (name) VALUES \r\n");
        var parameters = new ExpandoObject() as IDictionary<string, object>;

        var values = new List<string>();
        for (int i = 0; i < players.Count; i++)
        {
            var p = players[i];

            values.Add($"(@Name{i})");
            parameters[$"Name{i}"] = p.Name;
        }

        sb.Append(string.Join(", \r\n", values));

        sb.Append(" \r\nRETURNING id, name, tag;");

        // parameters = { Name1 = "Player1", Name2 = "Player2, ... etc} 

        var ret = connection.Query<Player>(sb.ToString(), parameters);

내 플레이어의 속성으로 ExpandoObject를 만든 다음 Dapper Query ()로 전달합니다. 그것은 작동하지만 꽤 더러운 것 같습니다. 이것을 개선하는 방법에 대한 제안?

전문가 답변

첫째, List<Player> 가장 바깥 쪽 매개 변수로 Execute 메서드에 전달하는 것은 기본적으로 다음과 같습니다.

foreach(var player in players)
    connection.Execute(
         "INSERT INTO players (name) VALUES (@Name) \r\n" + 
         "RETURNING id, name, tag;", player);

Dapper는 명령을 파이프 라인 처리 할 수있는 매우 구체적인 async 시나리오가 아닌 한 그것을 언 롤링합니다. Dapper 목록 매개 변수 확장을 지원하지만 이는 잎 수준 값을위한 것이며 in (...) 용으로 작성되었으므로 원하는대로 구문이 나오지 않습니다. 예로서:

DateTime dateStart = ...
int[] custIds = ...
var orders = conn.Query<Order>(@"
    select * from Order
    where OrderDate >= @dateStart and CustomerId in @custIds",
    new { dateStart, custIds }).AsList();

이것은 SQL이됩니다 :

select * from Order
where OrderDate >= @dateStart and CustomerId in (@custIds0, @custIds1, ...)

(배열의 항목 수에 따라 다름)

예상되는 사용법은 최근에 제안되고 논의 된 것입니다. 현재 는 지원되지 않습니다. 루프 풀기는 Execute 에서만 작동하지만 여기에 뭔가 를 추가 가능성이 점점 더 커지고 있습니다. 까다로운 점은 올바른 동작이 무엇인지 결정하는 것과 이것이 여러 개의 개별 작업 결과를 본질적으로 연결시킬 것으로 예상 되는지 여부입니다.

하나; LINQ를 통해 원하는 것을 할 수 있습니다.

var results = players.SelectMany(
    player => connection.Query<Player>("...", player)).AsList();

이는 작동해야하는 것을 제외하고는 "루프를 풀고 결과를 연결합니다"동작과 동일합니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow