161 votes

Comment mettre en correspondance des listes d'objets imbriqués avec Dapper ?

J'utilise actuellement Entity Framework pour l'accès à ma base de données, mais je voudrais jeter un coup d'œil à Dapper. J'ai des classes comme celle-ci :

public class Course{
   public string Title{get;set;}
   public IList<Location> Locations {get;set;}
   ...
}

public class Location{
   public string Name {get;set;}
   ...
}

Un même cours peut donc être dispensé en plusieurs endroits. Entity Framework fait le mappage pour moi, de sorte que mon objet Cours est rempli d'une liste de lieux. Comment puis-je faire cela avec Dapper, est-ce possible ou dois-je le faire en plusieurs étapes de requête ?

2 votes

1 votes

6voto

Eduardo Pires Points 11

Il manque quelque chose. Si vous ne spécifiez pas chaque champ de Locations dans la requête SQL, l'objet Location ne peuvent être remplies. Jetez un coup d'œil :

var lookup = new Dictionary<int, Course>()
conn.Query<Course, Location, Course>(@"
    SELECT c.*, l.Name, l.otherField, l.secondField
    FROM Course c
    INNER JOIN Location l ON c.LocationId = l.Id                    
    ", (c, l) => {
        Course course;
        if (!lookup.TryGetValue(c.Id, out course)) {
            lookup.Add(c.Id, course = c);
        }
        if (course.Locations == null) 
            course.Locations = new List<Location>();
        course.Locations.Add(a);
        return course;
     },
     ).AsQueryable();
var resultList = lookup.Values;

Utilisation de l.* dans la requête, j'avais la liste des lieux mais sans les données.

1voto

Kiichi Points 31

Je ne sais pas si quelqu'un en a besoin, mais j'en ai une version dynamique sans modèle pour un codage rapide et flexible.

var lookup = new Dictionary<int, dynamic>();
conn.Query<dynamic, dynamic, dynamic>(@"
    SELECT A.*, B.*
    FROM Client A
    INNER JOIN Instance B ON A.ClientID = B.ClientID                
    ", (A, B) => {
        // If dict has no key, allocate new obj
        // with another level of array
        if (!lookup.ContainsKey(A.ClientID)) {
            lookup[A.ClientID] = new {
                ClientID = A.ClientID,
                ClientName = A.Name,                                        
                Instances = new List<dynamic>()
            };
        }

        // Add each instance                                
        lookup[A.ClientID].Instances.Add(new {
            InstanceName = B.Name,
            BaseURL = B.BaseURL,
            WebAppPath = B.WebAppPath
        });

        return lookup[A.ClientID];
    }, splitOn: "ClientID,InstanceID").AsQueryable();

var resultList = lookup.Values;
return resultList;

0voto

Athul Points 390

Il existe une autre approche utilisant le résultat JSON. Bien que la réponse acceptée et les autres soient bien expliquées, je viens de penser à une autre approche pour obtenir le résultat.

Créez une procédure stockée ou une requête sélective pour renvoyer le résultat au format json, puis désérialisez l'objet résultat au format de la classe requise. Veuillez consulter l'exemple de code.

using (var db = connection.OpenConnection())
{                
  var results = await db.QueryAsync("your_sp_name",..);
  var result = results.FirstOrDefault();    

  string Json = result?.your_result_json_row;

  if (!string.IsNullOrEmpty(Json))
  {
     List<Course> Courses= JsonConvert.DeserializeObject<List<Course>>(Json);
  }

  //map to your custom class and dto then return the result        
}

Il s'agit d'un autre processus de réflexion. Veuillez revoir la même chose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X