Appeler une fonction sur chaque enregistrement à partir du résultat dapper

asp.net-mvc-5 c# dapper

Question

J'essaie d'appeler une fonction sur chaque enregistrement qui définira certaines valeurs de champ. Lorsque les résultats sont censés être recherchés, ceci est réalisé de la manière suivante:

public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        TotalPages totalRows = null;
        var list = oConn.Query<T, TotalPages, T>(myQuery, (e, t) =>
        {
            totalRows = t;
            if (mapAction != null) customAction(e);
            return e;
        }, param, splitOn: "SplitOn");
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = totalRows == null ? 0 : totalRows.TotalRows;
    }
    return obj;
}

Mon problème vient quand les résultats ne sont pas destinés à être recherchés. Ma requête dans le premier exemple inclut split on column et c'est pourquoi tout fonctionne, cependant ma prochaine requête est une simple requête, telle que Select Column1, Column2 FROM MyAwesomeTable qui retournera toutes les lignes, colonnes, etc.

Le problème est que je dois encore appliquer une action personnalisée à chaque résultat qui revient. Imaginons maintenant que quelques millions d'enregistrements potentiels reviennent (croyez-moi, ce n'est pas irréaliste compte tenu de ma situation). appliqué comme le dapper renvoie des résultats, tout comme il est dans le premier cas.

Voici ce que j'ai essayé:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var list = oConn.Query<T>(myQuery, (e) =>
        {
            if (mapAction != null) customAction(e);
            return e;
        }, param).ToList();
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = list.Count();
    }
    return obj;
}

J'ai une erreur pour le code ci-dessus qu'il ne peut pas résoudre la méthode. Query<T>(etc... Je comprends que c'est parce qu'il n'existe pas. Est-ce possible avec Dapper.

Réponse acceptée

Je crains que la réponse courte soit que vous ne pouvez pas le faire.

La réponse un peu plus longue est que dans votre requête paginée, il s’agit essentiellement d’un deuxième passage à travers les données, car Dapper effectue un certain travail pour traduire les données de chaque ligne en une instance de "T". que vous utilisez pour appeler votre "customAction".

Donc, il y aurait très peu de différence entre cela et faire un simple appel "conn.Query" non paginé suivi d'un passage ultérieur pour exécuter votre customAction. Quelque chose comme ce qui suit:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var results = oConn
            .Query<T>(myQuery)
            .ToList();
        obj.TotalRows = results.Count();
        obj.RowsFound = results
            .Select(value =>
            {
                customAction(value);
                return value;
            })
            .Cast<dynamic>();
    }
    return obj;
}

Si vous craignez que vous chargiez de nombreux enregistrements dans la requête non paginée, sachez que tous ces enregistrements seront chargés en mémoire en même temps; elles ne seront pas extraites de la base de données une par une au fur et à mesure que vous énumérerez les résultats renvoyés, ce qui pourrait représenter une perte considérable de ressources (si vous parlez de tant de données que vous vouliez éviter une seconde énumération) .

Cela doit être le cas car la connexion SQL est fermée lorsque GetNonPagedQuery est renvoyé et qu'il est donc impossible de la laisser ouverte pour lire les données "à la demande" de l'appelant. Si vous travaillez réellement avec des quantités massives de données, une requête non paginée n'est peut-être pas la meilleure approche?

Notez que dans le code ci-dessus, le "customAction" ne sera appelé que lorsque vous énumérez les lignes, celles-ci ne seront pas toutes déclenchées avant que GetNonPagedQuery ne revienne. Si "customAction" est potentiellement une opération coûteuse, cela peut vous être bénéfique. D'un autre côté, si vous voulez que "customAction" soit appelé pour chaque résultat avant que GetNonPagedQuery ne retourne, vous aurez besoin d'un appel ToList () supplémentaire après Cast <dynamic> ().


Réponse populaire

Oui, c'est peut-être:

Voir la section des documents Dapper sur le changement de type par ligne . Je doute (pas essayé moi-même) que cela ne fonctionnerait pas si vous utilisiez le même système pour masser les résultats dans le format souhaité en lisant chaque ligne et en la traitant explicitement.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow