【问题标题】:Can I map a result to Tuple in Dapper?我可以将结果映射到 Dapper 中的元组吗?
【发布时间】:2016-01-19 02:12:01
【问题描述】:

我正在尝试选择一个包含两个整数列的列表,将结果映射到Tuple<int,int>。例如:

connection.Query<Tuple<int, int>>("select id1, id2 from sometable").ToList();

不起作用,但如果我创建一个具有两个整数的类,则相同的查询确实有效,例如:

public class BogusClass {
    public int id1 { get; set; }
    public int id2 { get; set; }
}

connection.Query<BogusClass>("select id1, id2 from sometable").ToList();

我的偏好是不必为了获取一些数据而创建一些虚假的类。在这种情况下,它是两个整数列,但我可以想到其他用例。

编辑:我通过更改解决了这个问题

connection.Query<Tuple<int, int>>("select id1, id2 from sometable").ToList();

connection.Query<int, int, Tuple<int, int>>("select id1, id2 from sometable", Tuple.Create, splitOn: "*").ToList();

【问题讨论】:

    标签: c# dapper


    【解决方案1】:

    这从 C# 7 开始工作。这是Value Tuple

    public (int Id, DateTime? PublishDate) GetItem(string id)
    {
        const string sqlCommand = "select top 1 Id, PublishDate from Item where Id = @id";
    
        return _connection.Query<(int, DateTime?)>(sqlCommand, new { id }).FirstOrDefault();
    }       
    

    使用方法

    var item = GetItem(123);
    Console.WriteLine($"The publish date of item [{item.Id}] is [{item.PublishDate.Value}]");
    

    确保您已安装 Dapper 1.50.4 或更高版本。

    【讨论】:

    • Rubanov:在 Dapper 1.50.4 之前,我得到的只是具有默认值的值元组。 .net 4.7 项目中的 VS 2017
    【解决方案2】:

    这是一个工作示例:

    public class DapperTests
    {
        [Test]
        public void TuppleTest()
        {
            var conn = new SqlConnection(@"Data Source=.\sqlexpress; Integrated Security=true; Initial Catalog=mydb");
            conn.Open();
    
            var result = conn.Query<int, int, Tuple<int, int>>(
                "select 1,2 union all select 4,5", Tuple.Create, splitOn: "*").ToList();
    
            conn.Close();
    
            Assert.That(result.Count, Is.EqualTo(2));
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以这样

      string query = "Select value1 as Item1,value2 as Item2 from #sometable";
      var data = db.Query<Tuple<int,int>>(query);
      

      【讨论】:

        【解决方案4】:

        元组是一种选择,当我不想创建类时,我更喜欢使用动态结果,即,

        string sql = "Select 'f' as Foo, 'b' as Bar";
        
        var result = connection.Query<dynamic>(sql).Single();
        
        string foo = result.Foo;
        string bar = result.Bar
        

        结果返回的字段名称将是动态属性的名称。

        在您的情况下,您希望返回一个列表而不是分配给单个变量,因此元组会更合适:

        string sql = "select id1, id2 from sometable";
        
        List<Tuple<int, int>> result = conn.Query<int, int, Tuple<int, int>>( // *1
            sql,
            Tuple.Create, // *2
            splitOn: "*" ) // *3
            .AsList(); // *4
        

        *1 = &lt;int,int, Tuple&lt;int, int&gt;&gt; 告诉 dapper 会有两个整数返回一个元组

        *2 = 告诉 dapper 使用元组返回结果

        *3 = 告诉 dapper 返回的每个字段都用于为元组的每个属性返回一个结果。

        *4 = 将 Dapper 的内部结果转换为 List 的 Dapper 扩展方法;默认情况下,Dapper 在幕后返回一个列表,因此演员会比复制到新列表更快。

        【讨论】:

        • 感谢地铁蓝精灵。这是一个我不知道的很酷的功能,可能是更好的方法。我接受 Void Ray 的回答,因为从技术上讲,这就是我提出的问题的答案。
        【解决方案5】:

        对于那些使用异步的,这可以通过使用 ValueTuple 来实现。

        var res = await conn.QueryAsync<(int Id1, int Id2)>(sql);
        
        List<Tuple<int, int>> tuples = res.Select(x => new Tuple<int, int>(x.Id1, x.Id2)).ToList();
        

        【讨论】:

          【解决方案6】:

          这在 .NET core 3.1 中对我有用

          string sql = "SELECT UserAcctId, MinAge, MaxAge FROM [MemberDetails]";
          
          using IDbConnection dbConnection = new SqlConnection(_connectionString);
          dbConnection.Open();
          
          var results = dbConnection.Query<(int userAcctId, short minAge,  short maxAge)>(sql);
          foreach (var item in results) {
             if (item.minAge > 0) { 
              // do something
             }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-06-13
            • 2019-12-07
            • 1970-01-01
            • 2020-01-28
            • 2013-10-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多