【问题标题】:How to use generic and Nullable<T> types in Dapper for materialization?如何在 Dapper 中使用泛型和 Nullable<T> 类型进行物化?
【发布时间】:2014-11-13 08:10:20
【问题描述】:

我有这个电话:

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.Tuple2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Nullable1[[System.Decimal, mscorlib,版本=4.0.0.0,文化=中性, PublicKeyToken=b77a5c561934e089]],mscorlib,版本=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 物化

【问题讨论】:

    标签: c# generics tuples nullable dapper


    【解决方案1】:

    这里的问题不是Nullable&lt;T&gt;,而是Tuple&lt;,&gt;

    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&lt;T1,T2&gt; 没有这些。它有构造函数:

    public Tuple(T1 item1, T2 item2);
    

    which 不会在这里工作 - 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(耶!)

    【讨论】:

    • 感谢您的解释。我决定使用 KeyValuePair 并将我的列命名为“as KEY”和“as VALUE”。
    猜你喜欢
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多