Developpez.com - Rubrique .NET

Le Club des Développeurs et IT Pro

Accès aux données avec le micro-ORM Dapper

Un tutoriel de Thomas Levesque

Le 2013-10-29 14:17:30, par tomlev, Rédacteur/Modérateur
Bonjour,

Cette discussion est destinée à recevoir vos commentaires sur l'article Accès aux données avec Dapper

Pour accéder à une base de données avec .NET, on a traditionnellement le choix entre deux grandes approches : utiliser un ORM (Object-Relational Mapper), ou requêter directement en SQL à l'aide d'ADO.NET. Si les ORM permettent généralement de gagner du temps, ce sont aussi souvent des « usines à gaz », ce qui les rend peu adaptés pour certaines applications. Mais d'un autre côté, l'API ADO.NET pour requêter en SQL est un peu laborieuse à utiliser… Il faudrait donc un compromis entre les deux : c'est là qu'intervient Dapper, une petite librairie open-source qui appartient à la catégorie des micro-ORM.
  Discussion forum
19 commentaires
  • tomlev
    Rédacteur/Modérateur
    Envoyé par stailer
    En revanche, en .Net on a EntityFramework.
    Avec ce dernier on arrive à des résultats bien plus puissants et bien plus facile à écrire encore que dans les exemples qui sont fournis ici avec Dapper.

    Alors ma question : pourquoi Dapper ? c'est une question de performance ? ou alors il propose d'autres possibilités importantes et absentes de EntityFramework ?
    Si tu avais lu l'article tu ne poserais pas cette question

    En résumé, un ORM complet comme Entity Framework ou NHibernate, c'est certes puissant, mais c'est un peu "usine à gaz"... C'est très lourd, les performances ne sont pas optimales, on ne sait pas trop ce qui se passe derrière, etc

    Dapper n'a pas la prétention de faire tout ce que fait un vrai ORM ; il permet surtout de faire du SQL (avec les avantages que ça implique en terme de performance) tout en facilitant certaines tâches qui sont fastidieuses avec l'API ADO.NET standard (requêtes paramétrées, matérialisation d'objets métier).
  • tomlev
    Rédacteur/Modérateur
    Envoyé par stailer
    Ok, donc si si en effet j'avais bien compris l'article mais je ne pensais pas que EntityFramework était une usine à gaz.
    Pour être clair, je ne dis pas que Entity Framework est une grosse daube et qu'il ne faut surtout pas s'en servir... Je dis simplement que c'est pas adapté à toutes les applications. L'équipe de Stack Overflow s'est donné la peine de créer Dapper parce que les performances d'Entity Framework étaient insuffisantes, je pense pas qu'ils l'aient fait juste pour le plaisir...

    D'ailleurs, jette un oeil au comparatif de performances sur le site de Dapper, c'est assez éloquent (évidemment c'est sûrement pas totalement impartial, mais ça donne une idée)

    Envoyé par stailer
    En quelques clics tu mappes ta base.
    En une ligne tu te connectes et tu fais une requête linq sur des entités... Waouh en effet quelle usine !
    Je ne parle pas en terme d'utilisation ; évidemment que c'est super simple à utiliser. Mais ce qui se passe derrière et assez lourd, et pas du tout transparent. Tu ne contrôles pas (ou très peu) le SQL qui est généré, et si ce n'est pas optimal tu ne peux pas y faire grand chose. Le lazy loading est certes très pratique, mais ça implique des allers-retours supplémentaires vers la DB ; si tu fais des traitements en masse, c'est pas top... Je pourrais citer pas mal d'autres problèmes, mais j'ai la flemme des les écrire.

    Envoyé par stailer
    "On ne sait pas ce qui se passe derrière"
    Ah ok, parce que Dapper, si ? J'aimerais savoir déjà le nb de personnes qui ont regardé la totalité du code de Dapper avant de l'utiliser.
    Bah déjà tu écris le SQL toi-même... Tout ce que fait Dapper, finalement, c'est :
    - gérer la déclaration des paramètres de la requête à partir de l'objet de paramètres que tu passes (avec un cache par type pour ne pas faire de la réflexion à chaque appel)
    - matérialiser les entités à partir du contenu d'un DataReader (là aussi, avec un cache par type d'entité)

    Le code de Dapper n'est vraiment pas long, donc si tu veux fouiller dedans, c'est vite fait... en quelques minutes tu peux commencer à voir le principe. Par contre celui d'EF, je pense qu'il faudrait au moins quelques semaines avant de commencer à comprendre comment ça fonctionne.

    Envoyé par stailer
    Alors on va me dire : "ouais mais pour des besoins de grande performance c'est pas bon !". Ok mais alors si y a ce besoin, on est certainement pas dans le cadre d'une petite application mais bien de quelque chose de plus important : donc la ça coince, EF (ou autre) sera forcément plus adapté, notamment pour la maintenabilité du code.

    De plus, EntityFramework est fourni en standard dans VS et utilisé en prod par des centaines d'applis (davantage que Dapper) . Donc au niveau test et "confiance" je crois qu'il n'y a pas photo.
    Bah écoute, tu fais ce que tu veux... Continue à utiliser EF puisque tu es absolument certain que c'est forcément le meilleur choix dans toutes les situations.

    Moi, on m'a appris qu'il fallait toujours utiliser l'outil le plus adapté pour une tâche donnée ; parfois ce sera EF, parfois ce sera Dapper, parfois ce sera encore autre chose...
  • katkiller
    Membre éprouvé
    Je ne connaissais pas cette librairie !
    Elle a vraiment l'air très simple a utiliser (A essayer bien sûr) !

    Merci pour la découverte
  • Maître Kenobi
    Membre éprouvé
    Bonjour,

    peut-on facilement l'adapter au VB ?
  • tomlev
    Rédacteur/Modérateur
    Envoyé par Maître Kenobi 
    Bonjour,

    peut-on facilement l'adapter au VB ?

    Salut,

    Oui bien sûr, du moins je ne vois pas de raison que ce soit pas possible... par contre cela suppose de référencer le binaire (la solution consistant à inclure la source dans le projet ne fonctionnera pas, puisque ce n'est pas du VB)

    Ca donnerait quelque chose comme ça (si je ne me plante pas dans la syntaxe VB...) :

    Lecture d'une liste d'entités
    Code VB.NET :
    Dim contacts As IEnumerable(Of Contact) = connection.Query(Of Contact)("select * from Contact")
    Lecture de données arbitraires

    Code VB.NET :
    1
    2
    3
    Dim result = connection.Query("select count(*) as Count, max(Id) as MaxId from Contact").Single() 
    Dim count As Integer = result.Count 
    Dim maxId As Integer = result.MaxId

    Requête paramétrée :
    Code VB.NET :
    1
    2
    3
    Dim results = connection.Query(Of Contact)( _ 
        "select * from Contact where DateOfBirth < @maxDate and FirstName = @firstName", _ 
        New With { .maxDate = New DateTime(1950, 1, 1), .firstName = "George" })
  • stailer
    Membre chevronné
    Je crois avoir vu qu'avec EF aussi y a moyen de faire du SQL.

    Tu parles de perf... Euh alors dans ce cas la solution est toute trouvée : je pense que les procs stockées SQL Server sont plus performantes que EF et Dapper. Donc si vraiment t'as besoin de perfs, la solution la plus adaptée est sûrement celle là. A noter d'ailleurs qu'avec EF tu peux mapper aussi des procs stockées. Pourquoi s'en passer en cas de besoin de grandes perfs ?

    Ensuite, concernant les requêtes SQL émises par EF y a aussi moyen de voir ce qu'il créée... Je crois que c'est LinqPad dans lequel tu mets ta requête linq et il te montre ce qui va en résulter en SQL. Je m'en sers pas car j'ai pas eu le besoin mais bon, ça existe.
  • tomlev
    Rédacteur/Modérateur
    Envoyé par stailer
    Je crois avoir vu qu'avec EF aussi y a moyen de faire du SQL.
    Oui effectivement ; et dans ce cas ça revient un peu au même que ce que fait Dapper, sauf que les paramètres sont passés d'une façon un peu moins pratique à mon sens (un tableau d'objets).

    Envoyé par stailer
    Tu parles de perf... Euh alors dans ce cas la solution est toute trouvée : je pense que les procs stockées SQL Server sont plus performantes que EF et Dapper. Donc si vraiment t'as besoin de perfs, la solution la plus adaptée est sûrement celle là. A noter d'ailleurs qu'avec EF tu peux mapper aussi des procs stockées. Pourquoi s'en passer en cas de besoin de grandes perfs ?
    En fait si c'est pour faire une bête requête sur une table, je ne suis pas sûr que ça change grand chose de l'exécuter directement ou via une PS... A part peut-être lors de la 1e exécution d'une requête, parce que la PS sera déjà compilée, alors que la requête devra être parsée.

    Pour moi, l'intérêt des PS, c'est pas tellement les performances, c'est plutôt de limiter ce que peuvent faire les applis qui tapent dans la base (par exemple interdire les requêtes directes, mais autoriser les appels à certaines PS). Ca peut aussi être utile pour faire des choses plus complexes qu'une simple requête.

    Envoyé par stailer
    Ensuite, concernant les requêtes SQL émises par EF y a aussi moyen de voir ce qu'il créée... Je crois que c'est LinqPad dans lequel tu mets ta requête linq et il te montre ce qui va en résulter en SQL. Je m'en sers pas car j'ai pas eu le besoin mais bon, ça existe.
    Oui, tu peux faire ça dans Linqpad. Il y a aussi un moyen de le faire en code (pour logger les requêtes par exemple), je me rappelle plus comment exactement. Par contre tu ne peux pas contrôler ce que fait la requête... Par exemple si tu sais, d'après les index que tu as sur ta DB, les stats, qu'il serait plus efficace de faire un jointure qu'un SELECT imbriqué (ou inversement), tu ne peux pas forcer EF à le faire.

    C'est notamment pour ça que j'aime bien Dapper : il n'essaie pas de faire des choses qui pourraient être faites plus intelligemment par le développeur, il se contente des tâches qui ne demandent pas trop de réflexion mais qui sont fastidieuses à faire à la main.
  • stailer
    Membre chevronné
    Il y a aussi un moyen de le faire en code (pour logger les requêtes par exemple), je me rappelle plus comment exactement.
    Ca, ça m'intéresse en revanche... je savais pas qu'il y avait cette possibilité, je vais faire des recherches. N'hésite pas à me dire si tu retrouves....

    EDIT :
    Je teste ça dès que j'ai 5 minutes :

    Code :
    http://stackoverflow.com/questions/1102443/visualize-generated-sql-from-linq-to-entities
  • meziantou
    Membre émérite
    Ensuite, concernant les requêtes SQL émises par EF y a aussi moyen de voir ce qu'il crée...
    Certes mais parfois tu préfèrerai ne pas savoir ce qu'il génère
    http://weblogs.asp.net/gunnarpeipman/archive/2010/03/16/entity-framework-4-0-optimal-and-horrible-sql.aspx

    y a aussi un moyen de le faire en code (pour logger les requêtes par exemple), je me rappelle plus comment exactement.
    http://msdn.microsoft.com/en-us/library/system.data.objects.objectquery.totracestring.aspx
  • stailer
    Membre chevronné
    @meziantou Ok j'entends bien...

    Maintenant je peux te dire aussi qu'à une époque j'ai travaillé avec des gens qui s'en battait du sql et ça y allait à grand coup de "select *" ou de requêtes imbriquées parce qu'ils avaient oublié (ou ne savaient pas faire) les jointures...

    Alors bon... le SQL moisi de Linq, il a bon dos