Подтвердить что ты не робот

Как сопоставить объект словаря с результатами базы данных с помощью Dapper Dot Net?

Если у меня есть простой запрос, например:

string sql = "SELECT UniqueString, ID  FROM Table";

и я хочу сопоставить его со словарным объектом, например:

Dictionary<string, int> myDictionary = new Dictionary<string, int>();      

Как мне сделать это с помощью Dapper?

Я предполагаю, что это что-то вроде:

myDictionary = conn.Query<string, int>(sql, new {  }).ToDictionary();

Но не могу определить правильный синтаксис.

4b9b3361

Ответ 1

Там уже показаны различные способы; лично я просто использовал бы не общий api:

var dict = conn.Query(sql, args).ToDictionary(
    row => (string)row.UniqueString,
    row => (int)row.Id);

Ответ 2

Работает также без дополнительного класса:

var myDictionary = conn.Query<string, int, KeyValuePair<string,int>>(sql, (s,i) => new KeyValuePair<string, int>(s,i))
    .ToDictionary(kv => kv.Key, kv => kv.Value);

ПРИМЕЧАНИЕ. При использовании версии Dapper.NET 3.5 метод Query, который использует типы первого, второго и возвращаемого типов, требует указания дополнительных параметров, поскольку версии .NET 4.0 и .NET 4.5 используют преимущества необязательные аргументы.

В этом случае должен работать следующий код:

string splitOn = "TheNameOfTheValueColumn";
var myDictionary = conn.Query<string, int, KeyValuePair<string,int>>(sql, (s,i) => new KeyValuePair<string, int>(s,i), null, null, false, splitOn, null, null)
        .ToDictionary(kv => kv.Key, kv => kv.Value);

Большинство аргументов вернутся к умолчанию, но требуется splitOn, поскольку в противном случае оно будет иметь значение "id".

Для запроса, который возвращает два столбца, "ID" и "Описание", splitOn следует установить в "Описание".

Ответ 3

Я не уверен, что то, что вы пытаетесь сделать, возможно. Если вы определяете класс для сопоставления запроса, это становится намного более тривиальным:

public class MyRow
{
    public int Id { get; set; }
    public string UniqueString { get; set; }
}

Затем вы просто выполните следующее:

var sql = "SELECT UniqueString, ID  FROM Table";
var myDictionary = conn.Query<MyRow>(sql).ToDictionary(row => row.UniqueString, row => row.Id);

Ответ 4

string strSql = "SELECT DISTINCT TableID AS [Key],TableName AS [Value] FROM dbo.TS_TStuctMaster";
Dictionary<string,string> dicts = sqlConnection.Query<KeyValuePair<string,string>>(strSql).ToDictionary(pair => pair.Key, pair => pair.Value);

Вы можете использовать псевдонимы и сильные типы.

Псевдонимы являются ключевыми точками, которые соответствуют атрибутам типа KeyValuePair Key и Value.

Он работает при строгой типизации и работает хорошо.

Мне не нравится динамический тип. Это приносит катастрофу в определенных ситуациях. Более того, бокс и распаковка приносят потерю производительности.

Ответ 5

У Dapper также есть метод расширения для ExecuteReader. Таким образом, вы также можете сделать это:

var sql = "SELECT UniqueString, ID  FROM Table";
var rows = new List<Dictionary<string, int>>();
using (var reader = cn.ExecuteReader(sql)) {
    while (reader.Read()) {
        var dict = new Dictionary<string, int>();
        for (var i = 0; i < reader.FieldCount; i++) {
            dict[reader.GetName(i)] = reader.GetInt32(i);
        }
        rows.Add(dict);
    }
}

Этот подход работает без знания имен столбцов. Более того, если вы не знаете типы данных, вы можете изменить Dictionary<string,int> на Dictionary<string,object> и GetInt32(i) на GetValue(i).

Ответ 6

Если вы используете>.net 4.7 или netstandard2, вы можете использовать кортежи значений. код хорош и лаконичен и не имеет смысла в динамике.

var sql = "SELECT UniqueString, Id  FROM Table";
var dict = conn.Query<(string UniqueString, int Id)>(sql)
           .ToDictionary(t => t.UniqueString,t => t.Id);