Uno a muchos sin exponer colecciones secundarias y / o claves externas en el modelo

c# dapper orm

Pregunta

Tengo un problema con Dapper cuando no expongo mis claves externas y colecciones secundarias en el modelo POCO. Tomemos un ejemplo simple con las dos entidades:

Bike (Id, ModelName)
Tire (Id, Tread)

En la base de datos, cada neumático tiene una clave externa para la bicicleta. Pero mi modelo no. De la base de datos, quiero materializar esta estructura en un Dictionary<Bike, IEnumerable<Tire>> . Donde cada bicicleta (única) tendrá dos neumáticos.

Podría seleccionar esta relación de uno a muchos usando la siguiente consulta:

SELECT b.Id, b.ModelName, t.Id, t.Tread
FROM Bike b
JOIN Tire t ON b.Id = t.bike_id

Para mapear eso usando Dapper, he hecho lo siguiente:

var dbResult = connection.Query<Bike, Tire, KeyValuePair<Bike, Tire>>("sql-query-above",
(a, s) => new KeyValuePair<Bike, Tire>(a, s);
splitOn: "Id");

Y para convertir ese resultado en mi diccionario, usando LINQ:

Dictionary<Bike, IEnumerable<Tire>> dict = dbResult.GroupBy(g => g.Key, g => g.Value).ToDictionary(g => g.Key, g => g.AsEnumerable());

Y devuelve correctamente la estructura de datos:

Bike #1
 - Tire #1
 - Tire #2
Bike #2
 - Tire #3
 - Tire #4

Pero, ¿es esta la forma más eficiente de materializar esta estructura de datos? Una alternativa sería evitar el diccionario y crear otras entidades que expongan las claves y relaciones externas (por ejemplo, la colección de llantas en Bike y FK en Tyre), y utilizar un enfoque de mapeo como se describe aquí . Pero me gustaría evitar eso en mi modelo porque daría lugar a muchas clases adicionales. ¿Pero qué hay del rendimiento? ¿Es esto peor o lo mismo?

Respuesta popular

No soy un experto en el uso de Dapper, pero me he encontrado con limitaciones como la que estás experimentando. Tuve una situación similar en la que una de las propiedades en mi objeto era una colección como tú. Descubrí que era más simple crear una segunda consulta para llenar esos tipos internos de colecciones con un método de extensión.

Entonces, primero puedes agarrar todas las bicicletas y luego llamar a tu método de extensión para obtener los datos de los neumáticos, como:

dict.WithTires();    

Sé que es una segunda llamada a la base de datos, pero la compensación es que todavía puede tomar una bicicleta sin tener que obtener la información de los neumáticos cada vez.

Además, puede pensar en agregar la colección de neumáticos como una propiedad para su clase de bicicleta que en mi humilde opinión es mejor que usar un diccionario. Si tuvieras algo como esto:

public class Bike
{
    public int id { get; set; }
    public string modelName { get; set; }
    public IList<Tires> tires { get; set; }
}

public class Tires
{
    public int id { get; set; }
    public string tread { get; set; }
}

Puede crear fácilmente un método de extensión para obtener los datos de neumáticos de una bicicleta individual o una colección de bicicletas:

Bike myBike = new Bike();
List<Bike> bikeCollection = new List<Bike>();

myBike.WithTires();
bikeCollection.WithTires();


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué