ServiceStack ORMLite y Dapper Trabajando juntos Problemas

c# dapper ormlite-servicestack

Pregunta

Este es mi tercer día haciendo experimentos con ServiceStack ORMLite. Mi proyecto de ejemplo, que solía funcionar solo con Dapper, ahora es una mezcla de Dapper y ServiceStack ORMLite, y se lleva lo mejor de ambos mundos.

Anoche estaba luchando con una consulta Dapper. Básicamente es una combinación selectiva de 4 tablas que funcionaba bien antes de que entrara el código de ORMLite. Ahora falla una y otra vez la asignación de tabla contra objetos. No lo rompe simplemente asigna valores incorrectos a los objetos.

Tuve que seguir adelante así que como una solución temporal, lo que hice fue ejecutar cada una de las 4 selecciones sin la unión SQL utilizando un Dapper's QueryMultiple y más tarde, en C #, uniendo los resultados uno por uno.

Por favor, no empieces a reír. Sé que esto, por supuesto, no es la mejor solución. Sin embargo, todavía hace un viaje a DB, pero no se siente natural. Cuando la cantidad de filas aumenta, lo más probable es que se trate de un problema de rendimiento.

Esta mañana creo que encontré el origen de mi problema: me estoy cayendo y creando las tablas con ORMLite y me di cuenta de que el orden de los campos no es exactamente como esperaba. Antes del código ORMLite solo ejecutaba scripts SQL manualmente, así que decidí qué orden tenían los campos. Dado que mi proyecto necesita soportar MySql, Postgresql y SQL Server como desea el usuario final, sería una molestia mantener sincronizadas tres versiones de dichos scripts. Me gustaría automatizar este proceso con ORMLite y aprovecharlo, por supuesto.

Ahora déjenme explicar mi teoría y ustedes, muchachos expertos, pueden decidir si estoy en lo cierto o no. La consulta de Dapper utilizando combinaciones divide los resultados de cada tabla para asignarla a cada clase, según las convenciones de nomenclatura. Espera que el campo "Id" o "id" sea el primer campo en una tabla.

Sé que Dapper tiene una opción "SplitOn" para manejar tablas que no siguen su convención de nomenclatura ("IdProduct" como PK en lugar de "Id"), pero en mi caso no se puede usar así, ya que realmente no tengo ningún control sobre cómo se ordenan los campos en la función CreateTable de ORMLite. Podría terminar con "id" en el medio y, por lo tanto, causando el mismo problema que tengo ahora.

Quizás mirar mi código puede darte más pistas. Este es el código que funcionaba bien antes de ORMLite:

        using (var conn = this.ConnectionString.OpenDbConnection())
        {
            string sql = @"
                select  *
                from    insumo i
                join    unidadmedida um on um.id = i.idum
                join    lineainsumo l on l.id = i.idlinea
                left outer join archivo a on a.id = i.idimagen;";

            var insumos = conn.Query<Entities.Insumo, Entities.UnidadMedida,
                Entities.LineaInsumo, Entities.Archivo, Entities.Insumo>(sql, (i, um, l, a)
                    =>
                    {
                        i.UnidadMedida = um; i.Linea = l; i.Fotografia = a ?? new Entities.Archivo();
                        return i;
                    }).ToList(); //Dapper

            return insumos;
        }

Y esta es la solución temporal:

        using (var conn = this.ConnectionString.OpenDbConnection())
        {
            string sql = @"
                select * from insumo;
                select * from unidadmedida;
                select * from lineainsumo;
                select  a.*
                from    archivo a
                join    insumo i on i.idimagen = a.id;";


            var q = conn.QueryMultiple(sql); //Dapper
            var insumos = q.Read<Entities.Insumo>().ToList();
            var ums = q.Read<Entities.UnidadMedida>().ToList();
            var lineas = q.Read<Entities.LineaInsumo>().ToList();
            var archivos = q.Read<Entities.Archivo>().ToList();

            foreach (var i in insumos)
            {
                i.UnidadMedida = ums.FirstOrDefault(c => c.Id == i.IdUm);
                i.Linea = lineas.FirstOrDefault(c => c.Id == i.IdLinea);
                i.Fotografia = archivos.FirstOrDefault(c => c.Id == i.IdImagen) ?? new Entities.Archivo();
            }

            return insumos;
        }

Estuve investigando el código de ORMLite y parece que la función ToCreateTableStatement puede ser el lugar para modificar para resolver mi problema. ¿Tal vez podría funcionar agregar un atributo a cada campo en la definición de mi clase para indicar el orden de creación de campo deseado?

Estaba pensando en agregar esto al código de FieldDefinition :

public bool FirstField { get; set; }

Y agregando un atributo para decorar campos C # como este:

[Alias("name")]
public string Name { get; set; }

[Alias("id")]
[PrimaryKey]
[FirstField(true)]
public int Id { get; set; }

Luego, al crear el campo, el código podría seguir los valores de dicha propiedad y permitir controlar la posición final del campo en la tabla.

Por favor, avíseme si estoy en el camino correcto o, tal vez hay otra alternativa más elegante que esta.

Gracias por adelantado.

Respuesta aceptada

Parece ser más fácil anular el Id. Abstracto en cada clase en lugar de modificar el código fuente de ORMLite.

El cronograma del proyecto es estrecho para probar otro enfoque. Quizás para el próximo encuentro el tiempo para probar lo que gentilmente sugiere @mithz.



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é