À l'aide de Dapper.Net ORM, comment convertir une sortie de procédure stockée en un type concret?

c#-4.0 dapper metadata sql-server-2008-r2 stored-procedures

Question

Utilisation d'Entity Framework Je peux créer des classes concrètes à partir de la plupart des sprocs dans la base de données d'un projet sur lequel je travaille. Cependant, certains des sprocs utilisent un SQL dynamique et aucune métadonnée n'est renvoyée pour le sproc.

Donc, pour un tel sproc, j'ai créé manuellement une classe concrète et je veux maintenant mapper la sortie du sproc à cette classe et renvoyer une liste de ce type.

En utilisant la méthode suivante, je peux obtenir une collection d'objets:

                var results = connection.Query<object>("get_buddies", 
                    new {   RecsPerPage = 100,
                            RecCount = 0,
                            PageNumber = 0,
                            OrderBy = "LastestLogin",
                            ProfileID = profileID,
                            ASC = 1}, 
                        commandType: CommandType.StoredProcedure);

Ma classe concrète contient

[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class LoggedInMember : ComplexObject
{

   /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Int16 RowID
    {
        get
        {
            return _RowID;
        }
        set
        {
            OnRowIDChanging(value);
            ReportPropertyChanging("RowID");
            _RowID = StructuralObject.SetValidValue(value);
            ReportPropertyChanged("RowID");
            OnRowIDChanged();
        }
    }
    private global::System.Int16 _RowID;
    partial void OnRowIDChanging(global::System.Int16 value);
    partial void OnRowIDChanged();

    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.String NickName
    {
        get
        {
            return _NickName;
        }
        set
        {
            OnNickNameChanging(value);
            ReportPropertyChanging("NickName");
            _NickName = StructuralObject.SetValidValue(value, false);
            ReportPropertyChanged("NickName");
            OnNickNameChanged();
        }
    }
    private global::System.String _NickName;
    partial void OnNickNameChanging(global::System.String value);
    partial void OnNickNameChanged();
    .
    .
    .

Sans avoir à parcourir les résultats et à ajouter les paramètres de sortie à l'objet LoggedInMember, comment puis-je les mapper à la volée pour pouvoir en afficher une liste via un service WCF?

Si j'essaie var results = connection.Query<LoggedInMember>("sq_mobile_get_buddies_v35", ... j'obtiens l'erreur suivante:

System.Data.DataException: Erreur d'analyse de la colonne 0 (RowID = 1 - Int64) ---> System.InvalidCastException: la distribution spécifiée n'est pas valide. à Deserialize ...

Réponse acceptée

La solution consistait à créer un objet complexe dérivé du sproc avec EF:

    public ProfileDetailsByID_Result GetAllProfileDetailsByID(int profileID)
    {
        using (IDbConnection connection = OpenConnection("PrimaryDBConnectionString"))
        {
            try
            {
                var profile = connection.Query<ProfileDetailsByID_Result>("sproc_profile_get_by_id",
                    new { profileid = profileID },
                    commandType: CommandType.StoredProcedure).FirstOrDefault();

                return profile;
            }
            catch (Exception ex)
            {
                ErrorLogging.Instance.Fatal(ex);        // use singleton for logging
                return null;
            }
        }
    }

Dans ce cas, ProfileDetailsByID_Result est l'objet que j'ai créé manuellement à l'aide d'Entity Framework via le processus de création de type complexe (cliquez avec le bouton droit sur le diagramme, sélectionnez Ajouter / type complexe ... ou utilisez l'arborescence des types complexes du RHS).

UN MOT D'AVERTISSEMENT

Comme les propriétés de cet objet sont dérivées du sproc, EF n'a aucun moyen de savoir si une propriété est nullable. Pour tous les types de propriété nullable, vous devez les configurer manuellement en sélectionnant la propriété et en définissant sa propriété Nullable sur true .


Réponse populaire

En bigint que votre colonne SQL soit un bigint (c.-à-d. Int64 aka long ), votre type .Net a une propriété Int16.

Vous pouvez jouer avec la conversion et ignorer la procédure stockée en faisant quelque chose comme:

var results = connection.Query<LoggedInMember>("select cast(9 as smallint) [RowID] ...");

Où vous ne faites que sélectionner les propriétés et les types que vous souhaitez retourner votre objet. ( smallint est l'équivalent SQL d' Int16 )




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