Fonction générique dapper QueryMultiple

asp.net-mvc c# dapper generics

Question

J'utilise les procédures stockées asp.net mvc, dapper et MySql pour mon application Web. Jusqu'à présent, pour chaque page, j'ai 1 à 3 appels de procédures stockées. J'ai récemment découvert que mon hébergement ne proposait que 10 connexions parallèles et je souhaite donc combiner mes appels en un seul par page. J'ai déjà effectué les procédures stockées nécessaires dans la base de données, mais mon problème est d'utiliser dapper de manière générique pour obtenir les résultats des procédures.

Ce que je veux, c'est créer une fonction générique qui obtienne: 1) Nom de la procédure stockée. 2) Liste des types renvoyés par la procédure stockée. Et pour chaque type s'il s'agit de Single / ToList. La fonction générique doit donner une liste de variablese résultant de la procédure stockée.

L'exemple de la page dapper montre comment créer un appel QueryMultiple non générique:

var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
   var customer = multi.Read<Customer>().Single();
   var orders = multi.Read<Order>().ToList();
   var returns = multi.Read<Return>().ToList();
   ...
} 

En gros, ce que je veux, c'est insérer les types Customer, Order, Return dans un dictionnaire qui indiquera que chacun est Single ou ToList, puis fait quelque chose comme:

var result = new List<dynamic>();
var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
   foreach(var item in dictionary)
   {
       if (item.Value.equals("Single"))
           result.Add(multi.Read<item.Key>().Single());
       else if (item.Value.equals("ToList"))
           result.Add(multi.Read<item.Key>().ToList());
   }
}
return result;

Mon problème est que Visual Studio dit:

The type or namespace name 'item' could not be found

Pointage vers 'item' dans: multi.Read ()

Qu'est-ce que je fais mal? Existe-t-il un meilleur moyen d'implémenter une fonction générique utilisant QueryMultiple?

Réponse populaire

C'est un vieux sujet mais pensait que cela pourrait aider les autres. Dans ce cas, vous pouvez utiliser le code ci-dessous pour le faire fonctionner. Type de passe dans la fonction Read en tant que paramètre. Vous pouvez retourner dynamique. En utilisant Expando Object, vous pouvez générer des propriétés de manière dynamique.

Je préférerais créer un objet comme ci-dessous et passer la liste des objets à la fonction qui génèrerait le type de retour dynamique pour vous.

public class MapItem
{
    public Type Type { get; private set; }
    public DataRetriveTypeEnum DataRetriveType { get; private set; }
    public string PropertyName { get; private set; }

    public MapItem(Type type, DataRetriveTypeEnum dataRetriveType, string propertyName)
    {
        Type = type;
        DataRetriveType = dataRetriveType;
        PropertyName = propertyName;
    }
}

 //And then make a reusable function like below

public async Task<dynamic> ExecuteQueryMultipleAsync(IDbConnection con, string spName, object param = null,IEnumerable<MapItem> mapItems = null)
    {
        var data = new ExpandoObject();

        using (var multi = await con.QueryMultipleAsync(spName,param, commandType:CommandType.StoredProcedure))
        {
            if (mapItems == null) return data;

            foreach (var item in mapItems)
            {
                if (item.DataRetriveType == DataRetriveTypeEnum.FirstOrDefault)
                {
                    var singleItem = multi.Read(item.Type).FirstOrDefault();
                    ((IDictionary<string, object>) data).Add(item.PropertyName, singleItem);
                }

                if (item.DataRetriveType == DataRetriveTypeEnum.List)
                {
                    var listItem = multi.Read(item.Type).ToList();
                    ((IDictionary<string, object>)data).Add(item.PropertyName, listItem);
                }
            }

            return data;
        }
    }

Ci-dessous, comment vous appelez la méthode ci-dessus:

var mapItems = new List<MapItem>()
        {
            new MapItem(typeof(YourObject1), DataRetriveTypeEnum.FirstOrDefault, "Object1"),
            new MapItem(typeof(YourObject2), DataRetriveTypeEnum.List, "Object2")
        };

        var response = await ExecuteQueryMultipleAsync(name, request, mapItems);

        var object1 = response.Result.Object1;
        var listOfObject2 = ((List<dynamic>)response.Result.Object2).Cast<YourObject2>();

J'espère que cela t'aides.

À votre santé



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