如何使用Dapper Dot-Net从数据库结果映射到Dictionary对象
本文关键字:映射 Dictionary 对象 结果 数据库 何使用 Dapper Dot-Net | 更新日期: 2023-09-27 17:58:19
如果我有一个简单的查询,例如:
string sql = "SELECT UniqueString, ID FROM Table";
我想把它映射到一个字典对象,比如:
Dictionary<string, int> myDictionary = new Dictionary<string, int>();
我该如何处理Dapper?
我想是这样的:
myDictionary = conn.Query<string, int>(sql, new { }).ToDictionary();
但无法找出正确的语法。
已经展示了各种方法;就我个人而言,我只会使用非通用api:
var dict = conn.Query(sql, args).ToDictionary(
row => (string)row.UniqueString,
row => (int)row.Id);
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或netstandard2,则可以使用值元组。代码简洁明了,没有使用动力学。
var sql = "SELECT UniqueString, Id FROM Table";
var dict = conn.Query<(string UniqueString, int Id)>(sql)
.ToDictionary(t => t.UniqueString,t => t.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版本时,由于.NET 4.0和.NET 4.5版本利用了可选参数,因此采用第一、第二和返回类型的Query方法需要指定更多参数。
在这种情况下,以下代码应该有效:
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"answers"描述')的查询,splitOn
应设置为">描述'"。
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)
。
我不确定你想做的事情是否可行。如果您定义了一个类来将查询映射到它,那么这将变得更加琐碎:
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);
对于运行时不知道结构的表
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));
我个人更喜欢这样使用(1行):
var dict = dapper.Query<(string, int)>(sql).ToDictionary(x => x.Item1, row => row.Item2);