【问题标题】:How to map to a Dictionary object from database results using Dapper Dot Net?如何使用 Dapper Dot Net 从数据库结果映射到 Dictionary 对象?
【发布时间】:2013-02-08 20:25:09
【问题描述】:

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

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

我想将它映射到一个字典对象,例如:

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

我将如何使用 Dapper 做到这一点?

我认为是这样的:

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

但无法弄清楚正确的语法。

【问题讨论】:

    标签: c# asp.net dapper


    【解决方案1】:

    已经展示了多种方式;我个人只会使用非通用 api:

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

    【讨论】:

    • 我什至没有意识到您可以在查询方法中省略返回类型。
    • 仅供参考。返回的字段的属性名称区分大小写。在 Oracle 中,返回给我的字段都是大写字母,例如 row.UniqueString 从 Oracle 返回为 row.UNIQUESTRING。
    • @Colin 因为其他 RDBMS 允许区分大小写的名称(所以 .foo、.FOO 和 .Foo 都不同)我不确定我能做些什么,除了说“期待什么您的 RDBMS 返回"
    • 效果很好,但是这个解决方案使用动态对象,如果可能的话,我会尽量避免。查看 Allen.Cais 解决方案,没有动态对象:stackoverflow.com/a/51815558/4249619
    • @andreas 无论哪种方式,它都是同一个对象。它碰巧实现了动态工作所需的接口这一事实是分开的
    【解决方案2】:
    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的属性。

    它在强类型下工作并且运行良好。

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

    【讨论】:

    • 谢谢,这是最短和最简单的解决方案,同时仍然使用强类型。我猜动态类型的公认答案运行速度要慢得多。
    【解决方案3】:

    无需额外的类也可以工作:

    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 版本利用optional arguments.

    在这种情况下,下面的代码应该可以工作:

    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 应设置为“描述” .

    【讨论】:

    • Tim - 您的解决方案完全有效,但为了简单起见,我更喜欢 Marc 的解决方案。
    • 您能否解释一下无需额外课程也可以工作 您是否暗示我需要为Marcs solution 开设课程?两者都没有真正解释这一点
    • @Liam:我想我指的是w.brian's 方法。
    • 嗯,好的。感谢您的澄清
    【解决方案4】:

    如果您使用的是 > .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);
    

    【讨论】:

      【解决方案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&lt;string,int&gt; 更改为Dictionary&lt;string,object&gt;,将GetInt32(i) 更改为GetValue(i)

      【讨论】:

      • 漂亮的解决方案,正是我正在寻找的。谢谢。
      【解决方案6】:

      我不确定您尝试做的事情是否可行。如果您定义一个类来将查询映射到 this 就变得更简单了:

      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】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多