Dapper Multi Mapping

c# dapper

Pregunta

Tengo un objeto:

public class Species : IEntity<int>
{
     public int Id { get; set; }
     public string Name { get; set; }
     public SpeciesCategory Category { get; set; }
     public WetlandIndicator WetlandIndicator { get; set; }
}

public class SpeciesCategory : IEntity<int>
{
     public int Id { get; set; }
     public string Name { get; set; }
}

public class WetlandIndicator : IEntity<string>
{
     public string Id { get; set; }
     public string Designation { get; set; }
     public bool Status { get; set; }
}

Sin embargo, cuando uso Dapper para llamar a la siguiente consulta:

SELECT 
    [Species].*, 
    [SpeciesType].*, 
    [WetlandIndicator].Code AS Id, 
    [WetlandIndicator].Designation 
FROM 
    ((([Watershed].[Vegetation].[Species] INNER JOIN [Vegetation].[SpeciesCategory] 
        ON [Watershed].[Vegetation].[Species].[SpeciesCategoryId] = [Vegetation].[SpeciesCategory].[Id]) INNER JOIN [Watershed].[Vegetation].[SpeciesType] 
        ON [Watershed].[Vegetation].[Species].[SpeciesTypeId] = [Vegetation].[SpeciesType].[Id]) INNER JOIN [Watershed].[Vegetation].[WetlandIndicator] 
        ON [Vegetation].[Species].[WetlandIndicatorCode] = [Vegetation].[WetlandIndicator].[Code])

Recibo la splitOn que cuando se utiliza el mapeo múltiple, asegúrese de utilizar el atributo splitOn . Lo cual soy, pero todavía recibo el error. Así que supongo que tengo algún tipo de error de uso o error sintáctico. El código que continuamente comete errores es el siguiente:

public async Task<IEnumerable<SpeciesDomain>> GetAllSpecies(string query) =>
        await dbConnection.QueryAsync<Species, SpeciesCategory, WetlandIndicator, SpeciesDomain>(query, (species, speciesCategory, wetlandIndicator) =>
        {
            species.SpeciesCategory = speciesCategory;
            species.WetlandIndicator = wetlandIndicator;
            return species;
        }, splitOn: "Id, Code");

Nota importante: de forma predeterminada, Dapper utiliza Id, por lo que cambié el nombre de Code to Id, pero incluso con el código o el cambio de nombre, sigo recibiendo un error de asignación múltiple.

Respuesta aceptada

Parece que solo necesita eliminar el 'Código' de splitOn: "Id, Código". Su consulta cambia el nombre a "Id".

Dapper también usa "Id" como valor predeterminado, por lo que no es necesario especificarlo.

Dapper puede dividir la fila devuelta suponiendo que sus columnas Id se denominan Id o id. Si su clave principal es diferente o si desea dividir la fila en un punto que no sea Id, utilice el parámetro opcional splitOn.

A continuación hay una prueba rápida para verificar:

using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo"))
{
    var result = conn.Query<Species, SpeciesCategory, WetlandIndicator, Species>(
        "select Id = 11, Name = 'Foo', Id = 22, Name = 'Bar', Id = 33, Designation = 'House Cat' ", 
        (species, speciesCategory, wetlandIndicator) =>
    {
        species.Category = speciesCategory;
        species.WetlandIndicator = wetlandIndicator;
        return species;
    }).First();

    Assert.That(result.Id, Is.EqualTo(11));

    Assert.That(result.Category.Id, Is.EqualTo(22));
    Assert.That(result.Category.Name, Is.EqualTo("Bar"));

    Assert.That(result.WetlandIndicator.Id, Is.EqualTo(33));
    Assert.That(result.WetlandIndicator.Designation, Is.EqualTo("House Cat"));
}

Actualizar a la demo dividida por diferentes campos y tipos

public class Species
{
    public int Id { get; set; }
    public string Name { get; set; }
    public SpeciesCategory Category { get; set; }
    public WetlandIndicator WetlandIndicator { get; set; }
}

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

public class WetlandIndicator
{
    public string Code { get; set; }
    public string Designation { get; set; }
    public bool Status { get; set; }
}

using (var conn = new SqlConnection(@"Data Source=.\sqlexpress;Integrated Security=true; Initial Catalog=foo"))
{
    var result = conn.Query<Species, SpeciesCategory, WetlandIndicator, Species>(
        "select Id = 11, Name = 'Foo', Id = 22, Name = 'Bar', Code = 'X', Designation = 'House Cat' ", 
        (species, speciesCategory, wetlandIndicator) =>
    {
        species.Category = speciesCategory;
        species.WetlandIndicator = wetlandIndicator;
        return species;
    }, splitOn: "Id, Code").First();

    Assert.That(result.Id, Is.EqualTo(11));

    Assert.That(result.Category.Id, Is.EqualTo(22));
    Assert.That(result.Category.Name, Is.EqualTo("Bar"));

    Assert.That(result.WetlandIndicator.Code, Is.EqualTo("X"));
    Assert.That(result.WetlandIndicator.Designation, Is.EqualTo("House Cat"));
}

Respuesta popular

Entonces, descubrí la razón principal por la que falló. A Dapper no le gustó el parámetro splitOn que alterna entre int y string . Al obligar a todos a unificarse funcionó. El otro elemento que noté es que si tiene una columna llamada Code por ejemplo, que refleja una clave principal pero que SQL no está configurado a un identificador relacional, también generará un error.

Después de que fueron rectificados no tiró de ningún problema.



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é