IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

ASP.NET MVC Discussion :

Ajout dans deux tables en même temps asp.Net MVC3


Sujet :

ASP.NET MVC

  1. #21
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    Je ne vois aucun problème pour ajouter la sauvegarde en base de donnée.
    J'ai essayer sur son exemple avec entity framework (CF).
    L'action contient juste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     [HttpPost]
            public ActionResult Create(Parent parent)
            {
                if (ModelState.IsValid)
                {
                    db.Parents.Add(parent);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
     
                return View(parent);
            }
    Et j'ai bien parent et enfants en base de données. Après faut m'expliquer où est la complexité et l'impossibilité de le faire.
    Evidemment tu ne vois aucun problème pour ajouter dans la base de données des objets liés, puisque ce n'est pas là qu'il est. Le problème, c'est le comment on fait pour créer dynamiquement des enfants en nombre inconnu (voir question originale) et les INSERER EN UNE FOIS.... A ma connaissance, il n'est pas possible de garder en mémoire coté client des objets créés, attendre que la fiche parent soit elle aussi renseignée, et envoyer le tout;

    Il faut donc pouvoir entrer les enfants ligne par ligne AVANT que la fiche parent ne soit validée, sinon c'est, comme dit au tout début de cette conversation, 2 opérations distinctes. (en fait c'est bien ce qu'il faut faire, mais en utilisant ajax dans une grille pour les enfants, de manière à ce que cela est "l'air" d'être une même opération).

    Utiliser un tableau de dimension fixe est hors de question si on veut faire un travail propre, ce ne serait que du mauvais bricolage.

    Je n'ai jamais parlé "d'impossibilité", simplement dit que ce n'est pas aussi simple que cela en a l'air.

    Par ailleurs, et sur le plan purement base de données, une simple relation parents/enfants pour ce type de cas me parait plutot simpliste, justement. Il semblerait en effet logique d'envisager qu'un assuré puisse avoir son conjoint (et vice-versa) comme bénéficiaire, ce qui implique une relation récursive, un "parent" devrait aussi pouvoir être "enfant". Dans ce cas, il est encore plus clair qu'un tableau fixe serait une absurdité.

    Je dis et je répète, problème interessant parce que pas si simple qu'il en a l'air.

    Maintenant, on peut toujours s'en débarrasser vite fait mal fait en faisant un tableau de longueur délimitée et ne pas se soucier d'autre chose. Occasion perdue de faire du bon travail.

    Ce que j'aimerais voir comme code, puisqu'on est la pour apprendre, c'est celui de la méthode "public ActionResult Create()", celle qui génère la vue, et la vue elle-même, bien sûr, remplissant les conditions ci-dessus. En tous cas, si j'étais l'étudiante qui a posé la question, c'est ce que j'aimerais apprendre.

    Et si j'avais un projet comportant ce genre de demande, ce que j'ai expliqué ci-dessus est la manière dont je réaliserais cette fonctionalité.

  2. #22
    Membre habitué
    Homme Profil pro
    Inscrit en
    Avril 2013
    Messages
    76
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2013
    Messages : 76
    Points : 143
    Points
    143
    Par défaut
    Citation Envoyé par BernieG Voir le message
    Fais un exemple et mets-le quelque part où on peut le télécharger. Je ne demande qu'à apprendre, mais ce que tu viens d'écrire ne peut pas fonctionner, pour plusieurs raisons que je te laisse découvrir.
    Citation Envoyé par BernieG Voir le message
    Sans base de données, on peut faire beaucoup de choses qui ne veulent rien dire, et surtout, afficher est facile. Créer les enregistrements est une autre histoire.
    Citation Envoyé par BernieG Voir le message
    En effet, si on ne veut pas avoir à d'abord créer le parent, puis ses enfants, en 2 opérations séparées (la création des enfants serait sur une modification de la fiche parent), on se trouve tout de suite confronté à des situations que ni MS SQL, ni Entity Framework n'aiment beaucoup.....

    Tout d'abord, la seule manière que je connaisse de lier parents et enfants alors que l'objet parent n'est pas encore créé est d'utiliser une sequence, qui n'existe que depuis MS SQL Server 2012. Pour toute version antérieure, il faut créer l'équivalent, ce qui est loin d'être évident. De plus Entity Framework ne sait pas ce que sont les séquences, il faut donc le torturer quelque peu, en fait passer par une requête directe SqlQuery pour obtenir Next Value, et manuellement passer la valeur à la future clef primaire.
    Ce qu'elle a écrit marche avec Entity Framework et ce sans le moindre soucis. EF sait très bien gérer ces relations et j'ai même pas eu besoin de le torturer pour ça. Bien qu'on le fasse en une fois niveau code. EF lui va bien le faire en plusieurs étapes.

    Citation Envoyé par BernieG Voir le message
    A condition d'expliquer comment on fait pour créer plusieurs objets membreFamilles coté client sans les avoir envoyés 1 par 1 au serveur d'abord. Il faudrait pouvoir incrémenter la liste membreFamille coté client, mais ce n'est simplement pas possible. J'ai la vague impression que vous oubliez complétement l'aspect stateless qui défini le fonctionnement d'internet....
    On ne stock ni ne crée d'objet côté client. Ce qu'on fait c'est uniquement créer des données de formulaires qui les représentent.

    Citation Envoyé par BernieG Voir le message
    Ce que j'aimerais voir comme code, puisqu'on est la pour apprendre, c'est celui de la méthode "public ActionResult Create()", celle qui génère la vue, et la vue elle-même, bien sûr, remplissant les conditions ci-dessus. En tous cas, si j'étais l'étudiante qui a posé la question, c'est ce que j'aimerais apprendre.
    Bon niveaux modèle je suis partie de ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
        public class ModelContext : DbContext
        {
            public DbSet<MembreFamille> MembresFamilles { get; set; }
            public DbSet<Beneficiaire> Beneficiaires { get; set; }
            public ModelContext():base("DefaultConnection"){}
        }
     
        public class Beneficiaire
        {
            public int Id { get; set; }
            public string Nom { get; set; }
            public string Prenom { get; set; }
            public virtual IList<MembreFamille> MembreFamille { get; set; }
        }
     
        public class MembreFamille
        {
            public int Id { get; set; }
            public string Nom { get; set; }
            public int Prenom { get; set; } //Pour bien voir la validation
     
            [ForeignKey("Beneficiaire")]
            public int IdBenef { get; set; }
            public Beneficiaire Beneficiaire { get; set; }
        }
    Le contrôler pour gérer les bénéficiaire est un contrôleur des plus classique généré avec les outils. Pour les méthodes Create on a donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
           //
            // GET: /Beneficiaire/Create
     
            public ActionResult Create()
            {
                return View();
            }
     
            //
            // POST: /Beneficiaire/Create
     
            [HttpPost]
            public ActionResult Create(Beneficiaire beneficiaire)
            {
                if (ModelState.IsValid)
                {
                    db.Beneficiaires.Add(beneficiaire);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
     
                return View(beneficiaire);
            }
    Ceci est largement suffisant et fait tout ce dont on a besoin.

    Ce qui demande un poil plus de boulot est la vue.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    @model OneToMany.Models.Beneficiaire
     
    @{
        ViewBag.Title = "Create";
        int nbMembreFamille = 0;
        //Je récupère le ModelState de la vue 
        //Pour retrouver les données de validation
        var Errors = ViewContext.ViewData.ModelState;   
    }
     
    <h2>Create</h2>
     
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Beneficiaire</legend>
            <div class="editor-label">
                <label>nom</label>
                <input name="Beneficiaire.Nom" value="Nom B" />
                <label>prenom</label>
                <input name="Beneficiaire.Prenom" value="prenom B" />
            </div>
        </fieldset>
        <fieldset id="mbrFam">
                <legend>Membres Familles</legend>
                @if (Model != null && Model.MembreFamille != null)
                {
                    foreach (var item in Model.MembreFamille)
                    {
                      <!-- Champs Nom, la création d'un Helper pourrait éclaicir la génération des champs -->
    		 <label>nom</label>
    <input value="@Errors["Beneficiaire.MembreFamille[" + nbMembreFamille + "].Nom"].Value.AttemptedValue" name="Beneficiaire.MembreFamille[@nbMembreFamille].Nom">
                   @Errors["Beneficiaire.MembreFamille[" + nbMembreFamille + "].Nom"].Errors.Select(e=>e.ErrorMessage).FirstOrDefault();                                                                      
    <label>prenom</label>
    <!-- Champs prénom -->
    <input value="@Errors["Beneficiaire.MembreFamille[" + nbMembreFamille + "].Prenom"].Value.AttemptedValue" name="Beneficiaire.MembreFamille[@nbMembreFamille].Prenom">
                    @Errors["Beneficiaire.MembreFamille[" + nbMembreFamille + "].Prenom"].Errors.Select(e => e.ErrorMessage).FirstOrDefault();
                    nbMembreFamille++;
                    }
                }
        </fieldset> 
        <a id="btAdd">(+)</a>     
        <p>
            <input type="submit" value="Create" />
        </p>
    }
     
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
     
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        <script>
        var nbMembreFamille = @nbMembreFamille;
     
        var btAdd = document.getElementById("btAdd");
        //Génération des champs pour un membre supplémentaire
        btAdd.onclick = function ()
        {
            var fieldset = document.getElementById("mbrFam");
            fieldset.innerHTML += '<label>nom</label><input name="Beneficiaire.MembreFamille['+nbMembreFamille+'].Nom" value="Nom '+nbMembreFamille+'" /><label>prenom</label><input name="Beneficiaire.MembreFamille['+nbMembreFamille+'].Prenom" value="prenom '+nbMembreFamille+'" />';
            nbMembreFamille++;
            return false;
        }
        </script>
     
    }
    Après, il doit il y avoir des surcharges pour Html.ValidationFor ou Html.EditorFor qui pourrait faire l'affaire. Si elle n'existe pas, il n'est pas compliqué de créer les helpers qui générerait les champs.

    Le javascript que j'ai mis dans la vue ne fait qu'ajouter des champs. Il n'y a pas d'aller retour client/serveur.

    Donc pour Entity Framework et le contrôleur, il n'y a aucune difficulté.
    Pour la vue, il y a un peu de code à faire à la main mais rien de vraiment complexe.
    Niveau JS, la création des champs aurait pu être construit directement dans l'arbre DOM au lieux de jouer avec innerHTML. L'utilisation de innerHTML n'est pas des plus performantes mais ici plus lisible.

  3. #23
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2013
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2013
    Messages : 39
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par g.Arnaud Voir le message
    Le javascript que j'ai mis dans la vue ne fait qu'ajouter des champs. Il n'y a pas d'aller retour client/serveur.

    Donc pour Entity Framework et le contrôleur, il n'y a aucune difficulté.
    Pour la vue, il y a un peu de code à faire à la main mais rien de vraiment complexe.
    Niveau JS, la création des champs aurait pu être construit directement dans l'arbre DOM au lieux de jouer avec innerHTML. L'utilisation de innerHTML n'est pas des plus performantes mais ici plus lisible.
    Effectivement c'est une solution qui fonctionne. Je pense que je ne coderais jamais quelque chose comme ceci, plutot terrible coté interface utilisateur et possibilités de robustesse, mais bon, ça marche.

  4. #24
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    76
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 76
    Points : 43
    Points
    43
    Par défaut
    Bonjour,

    Si les 2 tables possèdent une clef etrangère, Entity Framework fait le reste pour vous. Au moment du SaveChanges, il va créer le parent et chaque enfant (les éventuelles clef primaires auto-incrémentées ne sont pas à renseigner, il le fera tout seul)

    Il suffit d'avoir un objet parent contenant une liste d'objet enfant que l'on consolide dans le context avant de faire le SaveChange.

    En outre, le SaveChange est à faire qu'une seule fois, à la fin de la consolidation des objets.

    Je confirme aussi que cela ne pose absolument aucun pb.

    Quant au mécanimse de l'interface, il s'agit simplement d'ergonomie...

Discussions similaires

  1. [MySQL] Insertion dans deux tables au même temps
    Par roy2work dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 21/10/2013, 23h58
  2. [AC-2007] Enregistrer dans deux tables en même temps.
    Par vadorequest dans le forum IHM
    Réponses: 4
    Dernier message: 24/02/2011, 09h09
  3. Insertion dans deux Tables en même temps
    Par hajoura89 dans le forum Développement Web en Java
    Réponses: 7
    Dernier message: 19/08/2010, 00h10
  4. Ajouter dans deux tables
    Par mikedimoi dans le forum Débuter
    Réponses: 4
    Dernier message: 11/01/2006, 20h49
  5. Comptez sur deux tables en même temps
    Par genova dans le forum Langage SQL
    Réponses: 12
    Dernier message: 13/09/2004, 18h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo