Partage
  • Partager sur Facebook
  • Partager sur Twitter

Entityframework - Mapping d'entité customisé

Sujet résolu
    28 août 2019 à 15:43:17

    Bonjour à tous,

    Aujourd'hui je me dirige vers vous pour avoir quelques conseils.

    Voilà mon problème :

    Je travaille avec EntityFramework 6 Base-first. J'ai besoin de mapper des entités que j'ai moi même crée avec les tables de ma base de données.

    Imaginons que j'ai une table SQL CLIENT comme ceci :

    CREATE TABLE CLIENT(
    id int primary key,
    info1 varchar, 
    info2 varchar,
    info3 varchar,
    info4 varchar,
    info5 varchar);

    et une classe c# Client comme celà :

    public class Client{
     private int id {get; set;}
     private string info2 {get; set;}
     private string info5 {get; set;}
    }

    J'aimerai pouvoir manipuler cette classe Client au sein d'un DbContext comme je le ferai avec une classe auto-generé par l'EDMX, et ainsi manipuler seulement les informations dont mon appli à besoin, et donc pouvoir par exemple faire

    using(var ctxt = new CustomDbContext())
    {
         ctxt.Entry(client).State = client.id == 0? EntityState.Added : EntityState.Modified;
    
        context.SaveChanges();
    }

    pour pouvoir ajouter ou mettre à jour un enregistrement de client dans ma table CLIENT, sans écraser les autres valeurs que je n'utilise pas (ici info1, info3 et info4)

    Merci à tous ceux qui pourront m'aider

    EDIT : Probleme résolu : https://www.c-sharpcorner.com/UploadFile/ff2f08/table-splitting-in-entity-framework-6-code-first-approach/

    -
    Edité par earp91 28 août 2019 à 17:50:36

    • Partager sur Facebook
    • Partager sur Twitter
      2 septembre 2019 à 4:19:41

      Salut,

      Une petite question juste au passage, tellement j'y connais rien en C# :  à quoi cela sert il de déclarer des données en accessibilité privée si c'est pour donner des fonctions get et (surtout) des fonctions set ??? (d'autant que, a priori, id est une valeur qui n'a absolument aucune raison d'être modifiée une fois qu'elle a été définie :-°:'( )

      La loi de Déméter, ca ne parle vraiment à personne en C# ?

      • Partager sur Facebook
      • Partager sur Twitter
      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
        2 septembre 2019 à 10:26:09

        Si, si, mais comme en C++, ça vient pas tout seul. ;-)
        • Partager sur Facebook
        • Partager sur Twitter
        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
          2 septembre 2019 à 11:09:36

          C'est une erreur de ma part.

          En écrivant l'exemple j'ai été trop vite et ai écrit "private" plutot que public.

          Sinon, non, ca ne me parle pas la loi de Déméter.

          • Partager sur Facebook
          • Partager sur Twitter
            2 septembre 2019 à 12:42:47

            Ben on va essayer de corriger cela, alors :D

            La loi de Déméter dit en substance que

            Si un objet t de type T utilise en interne un objet de type U, l'utilisateur de t ne devrait pas avoir à connaitre le type U pour manipuler son T.

            Bien sur, on pourra faire valoir -- avec raison -- que int et string sont deux abstractions "tellement simples" qu'elles forment "la base" de toute la logique que l'on pourra mettre en œuvre.

            Mais il existe une autre loi, appelée loi de Murphy, qui dit que

            L'utilisateur est un imbécile distrait qui n'attend qu'une occasion de faire une connerie

            Bien sur, ce n'est une loi empirique, mais elle est tellement souvent confirmée en programmation qu'il devient criminel de ne pas en tenir compte. D'autant plus qu'elle est soutenue par une autre loi empirique (la loi de l'emmerdement maximum ) disant

            Tout ce qui peut mal tourner tournera forcément mal, et de préférence au pire moment qui soit

            qui elle aussi se vérifie très régulièrement. (demande au malheureux commercial qui s'est retrouvé avec un écran bleu de la mort en présentant windows Xp juste au moment où il disait que cette nouvelle version était beaucoup plus stable :D ).

            Mais, revenons à nos moutons, et voyons pourquoi ces trois lois risquent de poser problème...

            Un "agragat" de données (quel que soit le langage, quel que soit le genre de l'agrégat) -- aussi simple soit-il -- est souvent beaucoup plus que la somme des données -- aussi simples soient-elles -- qui le composent, parce que les données qui le composent sont souvent dépendantes entre elles et soumises à des règles bien précises.

            Un exemple tout bête de ce que j'explique est la notion de date, que l'on pourrait parfaitement représenter au travers de trois valeurs numériques entières (jour, mois et année), mais dont la valeur maximale du jour dépend de la valeur du mois et de celle de l'année: la plupart des mois de l'année étant composés "d'office" de 30 ou 31 jours, à l'exception du mois de février, qui sera "le plus souvent" composé de 28 jours, mais qui sera composé de 29 jours lorsque l'année est bissextile. Le tout sans oublier le fait que la valeur maximale admise pour représenter le mois est -- elle aussi -- clairement définie :-°:'(

            Si on laisse l'utilisateur manipuler "impunément" ces trois valeurs numériques, les lois de Murphy et de l'emmerdement maximum nous dit que tôt ou tard, il y aura bien un utilisateur "assez distrait" que pour définir totalement incorrect (comme le 32 janvier ou le 30 février).

            Ce qui pose tout le problème des mutateurs  (type nom {get; set;} ), parce qu'ils impliquent que ce sera à l'utilisateur de définir lui-même la nouvelle valeur de la donnée, en risquant "d'oublier" de respecter une des règles imposée par l'agrégat de donnée.

            La loi de Déméter nous incite à faire en sorte que toutes les modifications de valeur d'une donnée faisant partie d'un agrégat passe systématiquement par une fonction qui s'assurera que l'ensemble des règles auxquelles la donnée est soumise sera vérifiée, et qui puisse refuser la modification si elle devait provoquer une incohérence au niveau de l'agrégat de données.

            Dans le cas qui nous occupe, laisser la possibilité à l'utilisateur de modifier la valeur du champs id, alors qu'il représente la clé primaire dans une base de données, provoquerait des catastrophes sans nom, parce que cela aurait pour résultat le fait que les autres données soient "reliés" à un client différent, avec comme conséquence, le fait que ces données seront -- a priori -- totalement erronées pour ce "nouveau" client.

            Autrement dit, comme le dit si bien Scott Meyers

            Make your interfaces easy to use correctly and hard to use incorrectly

            (Rendez vos interfaces faciles à utiliser correctement et difficiles à utiliser de manière incorrecte)

            PS : j'ai bien conscience d'avoir largement débordé du seul cadre de la loi de Déméter. J'espère que cela t'aura permis de prendre toute la mesure du problème, en plus de te donner des pistes de réflexion quant à la manière de l'éviter ;)

            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
              3 septembre 2019 à 11:45:15

              Merci bien pour ses explications et d'avoir pris le temps de les écrire.

              En fait il s'agit de l'encapsulation. Je connaissais ces principes, sans le nom de leur loi, mais cela fait toujours du bien d'avoir une piqûre de rappel.

              Dans mon contexte, mon "client final" est une API, donc j'ai la main sur l'ensemble des actions pouvant être exécutées par les utilisateurs. 

              Cependant, il est vrai que dans la théorie, il vaudrait mieux mettre les accesseurs (en tout cas les setters) en private pour au cas où un autre développeur reprendrai la main, pour ainsi lui éviter des erreurs.

              • Partager sur Facebook
              • Partager sur Twitter
                3 septembre 2019 à 16:00:29

                Mais, justement, les services rendus par ta classe ne doivent pas être des mutateur (setters)!

                C'est toute la différence entre un setter "classique" (ex : setPosition(Position newpos) et des fonctions comme move(diffX, diffY) ou comme moveTo(Position where) : La première évite à l'utilisateur de savoir où se trouve l'objet, et s'occupe d'évaluer la nouvelle position sur base des restrictions subies par l'objet, la deuxième s'assure explicitement que la position indiquée (where)

                • est susceptible d'être atteinte et
                • respecte les éventuelles restrictions auxquelles sont soumises les positions
                • Partager sur Facebook
                • Partager sur Twitter
                Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                  3 septembre 2019 à 17:18:54

                  Je comprends ce que tu veux dire mais je ne vois pas en quoi cela s'applique à mon cas.

                  Ce sont des classes de modèles, par essence elles reprennent donc la structure de mes différentes tables en BDD.

                  Je convertis ensuite des objets de ces classes dans des DTO.

                  Ces classes DTO ne rendent aucuns services si ce n'est l'accès à leurs données.

                  Mettre du code là dedans serait, selon moi, une bêtise.

                  Les restrictions de ces objets et les règles métiers qui régissent leurs relations sont définies au sein d'interfaces au sein desquels sont manipulés ces objets.

                  Ou alors y'a encore quelque chose que je n'ai pas compris ? Qu'est ce que je devrais faire selon toi ? 

                  -
                  Edité par earp91 3 septembre 2019 à 17:19:33

                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 septembre 2019 à 19:28:34

                    earp91 a écrit:

                    Je comprends ce que tu veux dire mais je ne vois pas en quoi cela s'applique à mon cas.

                    Ce sont des classes de modèles, par essence elles reprennent donc la structure de mes différentes tables en BDD.

                    Je convertis ensuite des objets de ces classes dans des DTO.

                    Ces classes DTO ne rendent aucuns services si ce n'est l'accès à leurs données.

                    Et c'était bien l'origine de ma toute première intervention : pourquoi se faire ch...er à placer des données dans l'accessibilité privée, si c'est pour fournir, par la suite, des accesseurs (get) et des mutateurs (set) ?

                    La seul champs de la structure qui mériterait éventuellement de subir une partie de ce traitement -- mise dans l'accessibilité privée, fourniture du seul accesseur) --  étant le champs id, à moins qu'il ne soit possible de le placer dans l'accessibilité publique,mais de lui imposer la constance, pour une vague question "d'homogénéité de l'interface".

                    Seulement, cela fait tellement longtemps que je n'ai plus pratiqué C# que je ne sais absolument plus s'il est possible d'imposer la constance au champs d'une structure :-°:'(

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                      4 septembre 2019 à 11:11:50

                      Pourquoi ne pas laisser "remonter" la classe auto-généré par l'EDMX, lui associé une Interface ayant juste les champs nécessaires et ne se servir que ce cette interface ?
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        4 septembre 2019 à 11:35:23

                        Je n'ai pas réfléchi à cette possibilité.

                        Est ce que tu pourrais nous montrer un exemple avec le cas d'utilisation que j'ai presenté au dessus ? C'est à dire un exemple d'interface et surtout un appel à celle-ci pour manipuler un objet ?

                        Merci

                        Cependant, est ce que le fait d'utiliser cette interface, qui contiendra une partie des champs seulement, n'écrasera pas les valeurs des autres champs par NULL ?

                        -
                        Edité par earp91 4 septembre 2019 à 11:36:39

                        • Partager sur Facebook
                        • Partager sur Twitter
                          4 septembre 2019 à 16:01:28

                          >Est ce que tu pourrais nous montrer un exemple avec le cas d'utilisation

                          C'est juste définir un interface et faire en sorte que la classe que vous utilisez comme DTO implémente cette interface (via héritage ou classe partielle, etc...)

                          La couche réceptrice de ces objets ne connaitra que l'interface, pas la classe générée par EF.

                          >n'écrasera pas les valeurs des autres champs par NULL

                          C'est "customisable" :

                          https://stackoverflow.com/questions/48937489/in-ef-core-how-to-select-specific-column-and-also-save

                          (il y a peut-être plus "moderne" comme méthode, à chercher)

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                            4 septembre 2019 à 16:52:00

                            D'accord je vois le cheminement.

                            Le problème avec le "customisable" dans mon contexte, c'est que je travaille avec un Repository générique pour les actions EF.

                            On retombe donc dans le découpage "Table per Hierarchy".

                            En fait je me rend compte que c'est ce ***** de Repository générique qui m'oblige à prendre des dispositions comme celles là. Je vais essayer de réfléchir à une autre solution pour gérer EF en mode deconnecté

                            -
                            Edité par earp91 4 septembre 2019 à 16:53:17

                            • Partager sur Facebook
                            • Partager sur Twitter
                              4 septembre 2019 à 18:27:29

                              Je crois que c'est fait pour et qu'il ne demande qu'à être spécializé ce pauvre Repository générique.
                              Rajoute une couche d'abstraction ITypeRepository ?

                              Ca rajoute pas mal d'interface et de class mais elles seront peu volumineuses.

                              -
                              Edité par LilyKianii 4 septembre 2019 à 18:27:58

                              • Partager sur Facebook
                              • Partager sur Twitter
                                5 septembre 2019 à 11:18:48

                                J'avais vu quelque chose pour non pas specialisé mon Repository, mais ajouter une interface à mes modèles, afin de préciser quelles propriétés ont été modifiées.

                                Il s'agit de ca : 

                                https://www.oreilly.com/library/view/programming-entity-framework/9781449331825/ch04.html#state_tracking_interface_updated_to_incl

                                Des avis ? Ca me semblait un peu lourd comme implémentation, sans parler du fait que dans l'exemple ils écrivent en dur le nom des propriétés, mais je suppose qu'on peut faire mieux avec "nameof"

                                -
                                Edité par earp91 5 septembre 2019 à 11:20:05

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  5 septembre 2019 à 15:14:55

                                  Je trouve que c'est un peu méli-mélo pour pas grand chose. Ça offre une certaine flexibilité sur ce que tu balades cependant.

                                  -
                                  Edité par LilyKianii 5 septembre 2019 à 15:16:20

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Entityframework - Mapping d'entité customisé

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown