Saltar al contenido

Dapper Multi Mapping con QueryMultiple

Siéntete libre de divulgar nuestro sitio y códigos con tus amigos, necesitamos tu ayuda para hacer crecer esta comunidad.

Solución:

Así es como lo hice funcionar:

var q = _sqlConnection.QueryMultiple("MySproc",
                                     myParams,
                                     commandType: CommandType.StoredProcedure);
var set1 = q.Read();

var set2Func = new Func((p, c) => 
    p.CheckAlert = c;
    return p;
);

var set2 = q.Read(set2Func, "CheckId")
            .GroupBy(x => x.PersonId)
            .Select(x => 
                var person = x.First();
                person.Checks = x.Select(p => p.Check).ToArray();
                person.Check = null; // i really don't like this
                return person;
            )
            .ToArray();

Como dice el comentario, no me gusta la propiedad de verificación innecesaria en el objeto Persona.

Todavía me encantaría saber de una mejor manera de hacer esto.

Aquí hay una versión de la solución que usé. Evité el problema que Ronnie planteó en su respuesta usando una jerarquía de herencia en lugar de establecer una propiedad para nullpero equivale a más o menos lo mismo.

Aquí está el SQL: los usuarios tienen artículos y colecciones, y los artículos pueden estar en colecciones.

CREATE TABLE Users
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
name NVARCHAR (MAX) NULL,
email NVARCHAR (128) NULL,
PRIMARY KEY (id))

CREATE TABLE Items
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
userId UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR (MAX) NULL,
description NVARCHAR (MAX) NULL,
PRIMARY KEY (id),
FOREIGN KEY (userId) REFERENCES Users (id))

CREATE TABLE Collections
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL,
userId UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR (MAX) NULL,
layoutSettings NVARCHAR (MAX) NULL,
PRIMARY KEY (id),
FOREIGN KEY (userId) REFERENCES Users (id))

CREATE TABLE CollectedItems
(itemId UNIQUEIDENTIFIER NOT NULL,
collectionId  UNIQUEIDENTIFIER NOT NULL,
PRIMARY KEY CLUSTERED (itemId, collectionId),
FOREIGN KEY (itemId) REFERENCES Items (id),
FOREIGN KEY (collectionId) REFERENCES Collections (id))

Ahora las clases del modelo de datos. Las colecciones son un poco más complicadas de lo que esperaría para manejar el mapeo múltiple de Dapper con múltiples consultas.

public class User

    public Guid Id  get; set; 
    public string Name  get; set; 
    public string Email  get; set; 
    public List Items  get; set; 
    public List Collections  get; set; 


public class Item

    public Guid Id  get; set; 
    public Guid UserId  get; set; 
    public string Name  get; set; 
    public string Description  get; set; 


public class CoreCollection

    public Guid Id  get; set; 
    public Guid UserId  get; set; 
    public string Name  get; set; 
    public string LayoutSettings  get; set; 


public class PartialDataCollection : CoreCollection

    public Guid ItemId  get; set; 


public class Collection : CoreCollection

    public List ItemIds  get; set; 


public class CollectedItem

    public Guid ItemId  get; set; 
    public Guid CollectionId  get; set; 
    public DateTime CreatedAt  get; set; 

Finalmente, tenemos el método del controlador que utiliza el mapeo múltiple de Dapper con múltiples consultas

[Route("GetUser/id")]
public User GetUser(Guid id)

    var sql = @"SELECT * FROM Users WHERE id = @id
                SELECT * FROM Items WHERE userId = @id
                SELECT * FROM Collections 
                    LEFT OUTER JOIN CollectedItems ON Collections.id = CollectedItems.collectionId  
                    WHERE userId = @id";
    using (var connection = new SqlConnection(ConnectionString))
    
        var multi = connection.QueryMultiple(sql, new  id = id );
        var user = multi.Read().Single();
        var items = multi.Read().ToList();
        var partialDataCollections = multi.Read(AddCollectedItem, splitOn: "itemId").ToList();

        user.Items = items;

        user.Collections = partialDataCollections.GroupBy(
            pdc => pdc.Id,
            (key, group) => new Collection
            
                Id = key,
                UserId = group.First().UserId,
                Name = group.First().Name,
                LayoutSettings = group.First().LayoutSettings,
                ItemIds = group.Select(groupMember => groupMember.ItemId).ToList()
            ).ToList();

        return user;
    


private PartialDataCollection AddCollectedItem(PartialDataCollection collection, CollectedItem collectedItem)

    if (collection != null && collectedItem != null)
    
        collection.ItemId = collectedItem.ItemId;
    
    return collection;

Donde Ronnie está ansioso por el escenario person.Check = null en su respuesta, estoy ansioso por la complejidad adicional en mi respuesta al agregar la clase PartialDataCollection a mi modelo. Pero no puedo ver una manera simple de evitar eso.

(NB, he planteado esto como un problema en el proyecto Dapper GitHub).

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *