如何从数据库结果映射到字典对象使用 Dapper 点网?

如果我有一个简单的查询,例如:

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

我想把它映射到一个字典对象,比如:

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

我要怎么和戴普合作?

我猜是这样的:

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

但不知道正确的语法。

62595 次浏览

我不确定你想做的事是否可行。如果您定义了一个类来将查询映射到这个类,那么这个类将变得非常琐碎:

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

作品也没有额外的类:

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”值。

对于返回两列“ 身份证”和“ 描述”的查询,应将 splitOn设置为“ 描述”。

已经展示了多种方法; 就我个人而言,我只会使用非通用 API:

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

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)

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 的属性匹配。

它在强键入下工作,运行良好。

我不喜欢动态类型。在某些情况下它会带来灾难。而且,拳击和拆箱会带来性能损失。

如果您使用 > 。Net 4.7或 netstandard 2可以使用值元组。代码很好很简洁,没有使用动力学。

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

对于运行时不知道其结构的表

    using var db = new SqlConnection(_connectionString);
var sql = $"Select * From {tableName} Order By {primaryKey}";


var result = await db.QueryAsync(sql);
return result
.Cast<IDictionary<string, object>>()
.Select(it => it.ToDictionary(it => it.Key, it => it.Value));