如何在Dapper中使用generic和Nullable <t>类型进行实现?</t>

时间:2014-11-13 08:10:21

标签: c# generics tuples nullable dapper

我有这个电话:

public IObservable<T> Subscribe(object topic, string service, string connectionString, string query)
{
    try
    {
        this.connection.ConnectionString = connectionString;
        this.connection.Open();
        this.connection.Query<T>(query, new { transactionid = topic }).ToObservable().Subscribe(message => this.subject.OnNext(message));
        return this.subject;
    }
    catch (Exception e)
    {
        this.subject.OnError(e);
        return this.subject;
    }
    finally
    {
        this.subject.OnCompleted();
        this.connection.Close();
    }
}

这是我的疑问:

with IDS as  (select L1_ID, L2_ID, L1_VALUE, L2_VALUE 
from MYDB where MYDB.ID = :transactionid) 
select * from 
(select L1_ID as ID, round(L1_VALUE, 28) as VALUE from IDS
union 
select L2_ID as ID, round(L2_VALUE, 28) as VALUE from IDS) UN

抛出此错误:

  

无参数默认构造函数或一个匹配签名   (System.String ID,System.Decimal VALUE)是必需的   System.Tuple 2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Nullable 1 [[System.Decimal,   mscorlib,版本= 4.0.0.0,文化=中性,   PublicKeyToken = b77a5c561934e089]],mscorlib,Version = 4.0.0.0,   Culture = neutral,PublicKeyToken = b77a5c561934e089]]具体化

1 个答案:

答案 0 :(得分:4)

此处的问题不是Nullable<T>,而是Tuple<,>

Dapper采用两种模式中的一种。我们假设我们的数据有列

ID      varchar
VALUE   decimal

(因为在您的方案中似乎就是这种情况)

要将其加载到T,它想要 (在确定0ID1VALUE等):

T row = new T() { ID = reader.GetInt32(0), VALUE = reader.GetDecimal(1) };

T row = new T(ID: reader.GetInt32(0), VALUE: reader.GetDecimal(1));

请注意,我在这里简化了很多东西,并且它对案例敏感性相当宽容,但基本上它想要的东西。

现在,问题是:Tuple<T1,T2> 没有这些。它有构造函数:

public Tuple(T1 item1, T2 item2);

哪个无法在这里工作 - dapper不能绝对确定什么意思去哪里,所以它不会尝试。这听起来很苛刻,但是dapper试图不介意列顺序,而在一般情况下(其中列不是所有不同的类型),目前尚不清楚正确的方法应该是什么不配。

选项:

  1. 创建表单的自定义类型:

    public class SomeType { // could also be a struct, immutable, whatever
        public int Id {get;set;}
        public decimal Value {get;set;}
    }
    

    并使用T === SomeType

  2. 使用非通用API并重新映射:

    Query(query, new { transactionid = topic }).Select(
        row => Tuple.Create((int)row.ID, (decimal)row.VALUE
    ).Whatever(...);
    
  3. 为结果列item1item2命名(是的!)