Dapper可以返回映射对象&其他非映射值?

时间:2017-02-08 08:09:25

标签: c# dapper .net-4.6

我使用dapper进行工作 示例查询(实际上我使用真实表格):

async void Main()
{
    var sql = @"SELECT PersonId = 1,
                FirstName = 'john',
                LastName = 'Lennon'";
    using (var conn = new SqlConnection(@"Data Source=....;Initial Catalog=W...."))
    {
        var person = await conn.QueryAsync<Person>(sql);
          person.Dump();
    }
}


public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

结果:

enter image description here

因此映射按预期工作。但有时我会查询返回另一个值,如:

SELECT PersonId = 1,
       FirstName = 'john',
       LastName = 'Lennon' , 
       cnt=(SELECT COUNT(1) FROM INFORMATION_SCHEMA.COLUMNS) //example

这完全合法:

enter image description here

问题:

是否可以返回Person对象其他非映射值(在同一select中)

类似的东西:

 await conn.QueryAsync<Person,int>(sql)

一个真实的例子:

SELECT  [AddressId]
      ,[PersonName]
      ,[Street]
      ,[Address_2]
      ,[House] , 
       cnt=(COUNT(1) OVER (PARTITION BY house)  )
  FROM [WebERP].[dbo].[App_Address]

所以我返回一个Address对象,其中包含与同一个表相关的计数,我不想要另一个选择。

4 个答案:

答案 0 :(得分:1)

是的,您可以使用QueryMultiple扩展名。但是你应该使用单独的select来获取列数:

SELECT PersonId = 1, FirstName = 'john', LastName = 'Lennon'
SELECT COUNT(1) FROM INFORMATION_SCHEMA.COLUMNS) 

然后得到两个结果

using(var result = sqlConnection.QueryMultiple(sql))
{
    var person = result.Read<Person>().Single();
    int count = multi.Read<int>().Single();
}

进一步阅读:Multiple Results部分。

返回附加值的另一种方法是动态查询。但在这种情况下,您必须手动构建Person对象:

var sql = @"SELECT PersonId = 1,
            FirstName = 'john',
            LastName = 'Lennon',
            cnt=(SELECT COUNT(1) FROM INFORMATION_SCHEMA.COLUMNS)";
var row = conn.Query(sql).Single();
var person = new Person { 
    PersonId = row.PersonId, 
    FirstName = row.FirstName, 
    LastName = row.LastName
};
int cnt = row.cnt;

AFAIK没有其他办法让人和cnt都返回。

答案 1 :(得分:1)

最简单的方法是将cnt添加到Person类中。你当然可以将它重命名为更有意义的东西。使它成为可为空的int,因此它将根据其在数据集中的存在而设置或不设置。

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? cnt { get;set; }
}

现在,这个cnt并不真正属于person类,但通常你不会将数据集分配给这样的类,你可以将它分配给类似DTO的东西,然后将它映射到你拥有的任何模型类或类中并以您认为合适的方式使用额外的属性。这将使您的业务类(例如Person)保持纯洁。

答案 2 :(得分:1)

你确定要这么做吗?正如歌曲所说的那样,保持生活的阳光。 查询应具有 a 返回类型。不同的查询应具有不同的返回类型。你说conn.Query<ReturnType>(SQL)的神奇之处就是你把手放在心上并承诺SQL会填充ReturnType。如果在一个地方,ReturnType具有查询永远不打算填充的字段,那对我来说就是代码气味。维护代码的人永远不会理解为什么会这样。如果稍后将来自不同查询的数据输入到单个方法中,请创建一个接口。

ORM思维的污染副作用是“正常化”的愿望。你的课程。如果在不同情况下做不同的事情,那么拥有数十个Person对象并不一定是个问题。在您的数据库中,您不希望在两个地方使用相同的数据。在您的应用中,您不希望在两个地方出现相同的行为。这些是非常不同的概念。如果您使用的是QueryFirst(免责声明:我写的),这一切都会简单得多,而且您不必将手放在心上。

答案 3 :(得分:0)

可以选择使用动态返回类型,如here所述 我更喜欢像Tuple这样的复合返回类型,它基本上是Dapper手册中描述的Multi Mapping。 (YMMV,我自己是Dapper的新手)