No se puede hacer que el mapeo múltiple funcione en Dapper

c# dapper multi-mapping

Pregunta

Jugar con Dapper, estoy bastante satisfecho con los resultados hasta ahora, ¡intrigante!

Pero ahora, mi próximo escenario sería leer datos de dos tablas: una tabla de Student y una de Address .

Student tabla del Student tiene una clave principal de StudentID (INT IDENTITY) , Address tiene un AddressID (INT IDENTITY) . Student también tiene un FK llamado AddressID en la tabla de Address .

Mi idea era crear dos clases, una para cada tabla, con las propiedades que me interesan. Además, puse una propiedad PrimaryAddress de Type Address en mi clase de Student en C #.

Luego intenté recuperar los datos del alumno y de la dirección en una sola consulta: imito la muestra que se muestra en la página de Github :

var data = connection.Query<Post, User>(sql, (post, user) => { post.Owner = user; });
var post = data.First();

Aquí, se recuperan una Post y un User , y el propietario de la publicación se establece para el usuario; ¿el tipo devuelto es una Post correcta?

Por lo tanto, en mi código, defino dos parámetros para el método de extensión de Query genérica: un Student como el primero que se debe devolver y una Address como el segundo, que se almacenará en la instancia del estudiante:

var student = _conn.Query<Student, Address>
                  ("SELECT s.*, a.* FROM dbo.Student s 
                        INNER JOIN dbo.Address a ON s.AddressID = a.AddressID 
                        WHERE s.StudentenID = @Id", 
                    (stu, adr) => { stu.PrimaryAddress = adr; },  
                    new { Id = 4711 });

El problema es - me sale un error en Visual Studio:

El uso del método genérico 'Dapper.SqlMapper.Query (System.Data.IDbConnection, string, System.Func, dynamic, System.Data.IDbTransaction, bool, string, int ?, System.Data.CommandType?)' Requiere 6 tipos de argumentos

Realmente no entiendo por qué Dapper insiste en usar esta sobrecarga con 6 argumentos tipo ...

Respuesta aceptada

Eso sería porque cambié las API y olvidé actualizar la documentación. Corregí el error.

Asegúrese de echar un vistazo a Tests.cs para obtener una especificación completa y actualizada.

En particular, la antigua API solía incluir una Action<T,U> para realizar la asignación, el problema era que se sentía arbitraria e inflexible. No se pudo controlar completamente el tipo de devolución. Las nuevas API tienen un Func<T,U,V> . Para que pueda controlar el tipo que obtiene del mapeador y no necesita ser un tipo mapeado.

Acabo de atar algo de flexibilidad adicional en el mapeo múltiple, esta prueba debería dejarlo en claro:

class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
}

class Address
{
    public int AddressId { get; set; }
    public string Name { get; set; }
    public int PersonId { get; set; }
}

class Extra
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public void TestFlexibleMultiMapping()
{
    var sql = 
@"select 
1 as PersonId, 'bob' as Name, 
2 as AddressId, 'abc street' as Name, 1 as PersonId,
3 as Id, 'fred' as Name
";
    var personWithAddress = connection.Query<Person, Address, Extra, Tuple<Person, Address,Extra>>
        (sql, (p,a,e) => Tuple.Create(p, a, e), splitOn: "AddressId,Id").First();

    personWithAddress.Item1.PersonId.IsEqualTo(1);
    personWithAddress.Item1.Name.IsEqualTo("bob");
    personWithAddress.Item2.AddressId.IsEqualTo(2);
    personWithAddress.Item2.Name.IsEqualTo("abc street");
    personWithAddress.Item2.PersonId.IsEqualTo(1);
    personWithAddress.Item3.Id.IsEqualTo(3);
    personWithAddress.Item3.Name.IsEqualTo("fred");

}

Dapper canaliza todas las API de mapeo múltiple a través de un único método, por lo que si algo falla, terminará en el 6 param. La otra pieza del rompecabezas fue que no permití algunas divisiones súper flexibles, que acabo de agregar.

Tenga en cuenta que el splitOn tendrá por defecto Id , lo que significa que tomará una columna llamada id o Id como el primer límite del objeto. Sin embargo, si necesita límites en varias claves principales que tienen diferentes nombres para decir un mapeo múltiple de "3 vías", ahora puede pasar una lista separada por comas.

Entonces, si tuviéramos que corregir lo anterior, probablemente lo siguiente funcionaría:

 var student = _conn.Query<Student,Address,Student>
              ("SELECT s.*, a.* FROM dbo.Student s 
                    INNER JOIN dbo.Address a ON s.AddressID = a.AddressID 
                    WHERE s.StudentenID = @Id", 
                (stu, adr) => { stu.PrimaryAddress = adr; return stu;},  
                new { Id = 4711 }, splitOn: "AddressID").FirstOrDefault();


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é