如何使用通用的,可空< T>类型为小巧玲珑物化? [英] How to use generic and Nullable<T> types in Dapper for materialization?

查看:436
本文介绍了如何使用通用的,可空< T>类型为小巧玲珑物化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的电话:

 公开的IObservable< T>订阅(对象的话题,串服务,字符串的connectionString,查询字符串)
{

{
this.connection.ConnectionString =的connectionString;
this.connection.Open();
this.connection.Query< T>(查询,新{transactionId,有无=话题})ToObservable()订阅(消息= GT; this.subject.OnNext(消息))。
返回this.subject;
}
赶上(例外五)
{
this.subject.OnError(E);
返回this.subject;
}
终于
{
this.subject.OnCompleted();
this.connection.Close();
}
}

这是我的查询:

 与IDS作为(选择L1_ID,L2_ID,L1_VALUE,从MYDB L2_VALUE 
式MYDB.ID =:transactionId,有无)
选择*从
(选择L1_ID为ID,圆(L1_VALUE,28)从IDS
工会
值选择L2_ID为ID,圆(L2_VALUE,28)从IDS VALUE)联合国

这抛出这个错误:




一个无参数的默认构造函数或者一个匹配的签名
(System.String ID,System.Decimal值)需要
System.Tuple 2 [System.String,mscorlib中,版本= 4.0.0.0,
区域性=中性,
公钥= b77a5c561934e089],[System.Nullable
1 [System.Decimal,
mscorlib程序,版本= 4.0.0.0,文化=中立,
公钥= b77a5c561934e089],mscorlib程序,版本= 4.0.0.0,
区域性=中性公钥= b77a5c561934e089]]物化



解决方案

这里的问题不是可空< T> ,它是在元组LT;,>



小巧玲珑假定的两种模式之一。假设我们的数据有列

  ID VARCHAR 
值小数点

(因为这似乎是在您的方案的情况下)



要加载到 T ,它想做的或者的(它已确定 0 是 ID 1 等):

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



  T行=新的T(ID:reader.GetInt32(0),值:reader.GetDecimal(1)); 



请注意,我简化了很多的东西在这里,它是相当宽容的约区分大小写,但是这的基本的想要的东西。



现在的问题是:元组LT; T1,T2> 没有任何的的的。它的构造器:

 公开元组(T1项目1,T2 ITEM2); 



其中的不会在这里工作的 - 短小精悍不能绝对肯定是什么意思,去的地方,所以它的不会尝试的。这听起来很刺耳,但短小精悍尝试不介意列顺序和在一般情况下的(这里的列是不是所有的不同类型的),目前尚不清楚正确的做法应该是什么时,有。不匹配



选项:




  1. 创建一个自定义类型形式:

     公共类SOMETYPE {//也可能是一个结构的,一成不变的,无论
    公众诠释标识{获取;集;}
    公共十进制值{获取;集;}
    }

    和使用 T === SOMETYPE


  2. 使用非通用API和再图:

     查询(查询,新{transactionId,有无=话题}) 。选择(
    行=> Tuple.Create((INT)row.ID,(十进制)row.VALUE
    ).Whatever(...);


  3. 命名结果列 ITEM1 项目2 (yeuch!)



I have this call:

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

This is my query:

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

This throw this error:

A parameterless default constructor or one matching signature (System.String ID, System.Decimal VALUE) is required for System.Tuple2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Nullable1[[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] materialization

解决方案

The problem here isn't the Nullable<T>, it is the Tuple<,>.

Dapper assumes one of two patterns. Let's assume our data has columns

ID      varchar
VALUE   decimal

(since that seems to be the case in your scenario)

To load that into a T, it wants to do either (after it has determined that 0 is ID and 1 is VALUE, etc):

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

or

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

note that I'm simplifying a lot of stuff here, and it is fairly forgiving about case sensitivity, but that's basically what it wants.

Now, the problem is: Tuple<T1,T2> doesn't have either of those. It has the constructor:

public Tuple(T1 item1, T2 item2);

which won't work here - dapper can't be absolutely sure what is meant to go where, so it doesn't try. This sounds harsh, but dapper tries not to mind about column order, and in the general case (where the columns aren't all different types), it is not clear what the correct approach should be when there is no match.

Options:

  1. create a custom type of the form:

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

    and use T === SomeType

  2. use the non-generic API and re-map:

    Query(query, new { transactionid = topic }).Select(
        row => Tuple.Create((int)row.ID, (decimal)row.VALUE
    ).Whatever(...);
    

  3. name your result columns item1 and item2 (yeuch!)

这篇关于如何使用通用的,可空&LT; T&GT;类型为小巧玲珑物化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆