ServiceStack ORMLite et Dapper Travailler ensemble Problèmes

c# dapper ormlite-servicestack

Question

Ceci est mon troisième jour à faire des expériences avec ServiceStack ORMLite. Mon exemple de projet, qui fonctionnait uniquement avec Dapper, est maintenant un mélange de Dapper et de ServiceStack ORMLite, prenant le meilleur des deux mondes.

Hier soir, je me débattais avec une requête Dapper. Il s’agit essentiellement d’une sélection de 4 tables qui fonctionnait correctement avant que le code d’ORMLite ne soit entré. Maintenant, il échoue encore et encore pour le mappage de la table sur les objets. Il ne casse pas, il attribue simplement des valeurs erronées aux objets.

J'ai dû passer à autre chose afin de contourner temporairement ce que je faisais en exécutant chacun des 4 sélections sans la jointure SQL en utilisant un QueryMultiple de Dapper et, plus tard, en reliant les résultats un par un.

S'il vous plaît ne commencez pas à rire. Je sais que ce n'est bien sûr pas la meilleure solution. Pourtant, il fait toujours un voyage à la DB, mais cela ne semble pas naturel. Lorsque le nombre de lignes augmente le plus probable, cela posera un problème de performance.

Ce matin, je pense avoir trouvé la source de mon problème: je dépose et crée les tables à l’aide d’ORMLite et je constate que l’ordre des champs ne correspond pas tout à fait à mes attentes. Avant le code ORMLite, je me contentais de lancer manuellement des scripts SQL, donc j'ai décidé quel ordre les champs avaient. Étant donné que mon projet doit prendre en charge MySql, Postgresql et SQL Server en tant que dernier utilisateur, il serait difficile de synchroniser trois versions de ces scripts. Je voudrais automatiser ce processus avec ORMLite et en profiter bien sûr.

Maintenant laissez-moi vous expliquer ma théorie et vous, les experts, pouvez décider si j'ai raison ou tort. La requête de Dapper utilisant des jointures divise les résultats de chaque table pour les mapper à chaque classe, en fonction des conventions de dénomination. Il s'attend à ce que le champ "Id" ou "id" soit le premier champ d'une table.

Je sais que Dapper a une option "SplitOn" pour gérer les tables sans suivre sa convention de nommage ("IdProduct" en tant que PK au lieu de "Id") mais dans mon cas, il ne peut pas être utilisé comme comment les champs sont classés sur la fonction CreateTable d' ORMLite . Il se pourrait que "id" soit au milieu et que cela cause le même problème que maintenant.

Regarder mon code peut peut-être vous donner plus d'indices. C'est le code qui fonctionnait bien avant 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;
        }

Et c'est la solution temporaire:

        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;
        }

Je cherchais dans le code d'ORMLite et il semble que la fonction ToCreateTableStatement soit l'endroit idéal pour modifier mon problème. Peut-être que l'ajout d'un attribut à chaque champ de ma définition de classe pour indiquer l'ordre souhaité de création de champ pourrait fonctionner?

Je pensais à l'ajouter au code FieldDefinition :

public bool FirstField { get; set; }

Et ajouter un attribut pour décorer les champs C # comme ceci:

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

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

Ensuite, lors de la création du champ, le code peut suivre les valeurs de cette propriété et permettre de contrôler la position du champ final sur la table.

S'il vous plaît laissez-moi savoir si je suis dans la bonne voie ou, peut-être il y a une autre alternative plus élégante que celle-ci.

Merci d'avance.

Réponse acceptée

Il semble plus facile de remplacer l'id abstrait sur chaque classe au lieu de modifier le code source d'ORMLite.

Le calendrier du projet est étroit pour essayer une autre approche. Peut-être pour le prochain, je peux trouver le temps d'essayer ce que @mithz suggère gentiment.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi