web-dev-qa-db-ja.com

Dapper Dot Netを使用してデータベース結果からDictionaryオブジェクトにマップする方法は?

次のような簡単なクエリがある場合:

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

そして、私はそれを次のような辞書オブジェクトにマッピングしたい:

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

Dapperでこれを行うにはどうすればよいですか?

私はそれが次のようなものだと思います:

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

しかし、適切な構文を理解することはできません。

55
jpshook

すでに示されているさまざまな方法があります。個人的には、非汎用APIを使用するだけです。

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

追加のクラスなしでも機能します。

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);

[〜#〜] note [〜#〜]:Dapper.NET 3.5バージョンを使用する場合、最初、2番目、および戻り値の型を取る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'になります。

2つの列を返すクエリの場合、「[〜#〜] id [〜#〜]」および「Description」、 splitOnは 'Description'に設定する必要があります。

19
Tim Schmelter
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タイプのキーと値の属性と一致します。

強い型付けの下で動作し、うまく動作します。

私は動的型が好きではありません。特定の状況で災害をもたらします。さらに、ボクシングとアンボクシングはパフォーマンスの低下をもたらします。

12
Allen.Cai

あなたがやろうとしていることが可能かどうかはわかりません。クエリをこれにマッピングするクラスを定義すると、はるかに簡単になります。

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);
7
w.brian

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
dalenewman

> .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);
3
herostwist