Comment utiliser générique et Nullable types dans Dapper pour la matérialisation?

c# dapper generics nullable tuples

Question

J'ai cet appel:

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

Ceci est ma requête:

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

Ceci jette cette erreur:

Un constructeur par défaut sans paramètre ou une signature correspondante (ID System.String, System.Decimal VALUE) est requis pour System.Tuple 2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Nullable 1 [[System.Decimal, mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089]], mscorlib, Version = 4.0.0.0, Culture = neutre, PublicKeyToken = b77a5c561934e089]] matérialisation

Réponse acceptée

Le problème ici n’est pas le Nullable<T> , c’est le Tuple<,> .

Dapper assume l'un des deux modèles. Supposons que nos données ont des colonnes

ID      varchar
VALUE   decimal

(puisque cela semble être le cas dans votre scénario)

Pour le charger dans un T , il veut faire soit (après avoir déterminé que 0 est ID et 1 est VALUE , etc.):

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

ou

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

Notez que je simplifie beaucoup de choses ici, et cela me pardonne assez au sujet de la sensibilité à la casse, mais c'est essentiellement ce qu'il veut.

Maintenant, le problème est le suivant: le Tuple<T1,T2> n’a aucun des deux . Il a le constructeur:

public Tuple(T1 item1, T2 item2);

ce qui ne marchera pas ici - Dapper ne peut pas être absolument sûr de ce qui est censé aller où, donc il n'essaie pas . Cela semble dur, mais Dapper ne se soucie pas de l'ordre des colonnes, et dans le cas général (où les colonnes ne sont pas toutes de types différents), il n'est pas clair quelle doit être l'approche correcte en l'absence de correspondance.

Options:

  1. créer un type personnalisé du formulaire:

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

    et utiliser T === SomeType

  2. utiliser l'API non générique et re-map:

    Query(query, new { transactionid = topic }).Select(
        row => Tuple.Create((int)row.ID, (decimal)row.VALUE
    ).Whatever(...);
    
  3. nommez vos colonnes de résultat item1 et item2 (yeuch!)



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi