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 Discussion :

Enregistrer USERID dans une table / Relation entre table identity Users et Table perso


Sujet :

ASP.NET

Vue hybride

AMP29 Enregistrer USERID dans une... 19/11/2024, 01h40
AMP29 Je crois que le problème... 19/11/2024, 02h54
popo C'est en effet, là qu'est ton... 19/11/2024, 11h02
AMP29 Merci pour ces infos. ... 19/11/2024, 15h07
AMP29 En fait, il n'y a pas la... 19/11/2024, 15h33
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut Enregistrer USERID dans une table / Relation entre table identity Users et Table perso
    Bonjour,

    Asp .Net 6.0 MVC

    J'enregistre des articles (commerce), et parmi les propriétés des articles, je voudrais que soit aussi enregistré l'id de l'user qui a créé l'article.
    Un User peut créer plusieurs articles.

    J'ai pensé faire ça dans ma classe 'Articles' :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        public class Articles
        {
            public long Id { get; set; }
            public string Nom { get; set; }
            public string Description { get; set; }
            public string Categorie { get; set; }
    etc... etc...
     
            public virtual ApplicationUser User { get; set; }
     
        }
    Avec pour le contexte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                modelBuilder.Entity<Articles>()
                    .HasOne(n => n.User)
                    .WithMany(a => a.Articles)
                    .OnDelete(DeleteBehavior.Cascade);
    Cela a créé une clé étrangère dans la table 'Articles'. C'était satisfaisant.
    Je pensais, jusqu'à ce que je finisse mon formulaire de création d'article et que je le teste, que l'id de l'utilisateur actuellement connecté allait automatiquement s'ajouter dans l'enregistrement de l'article dans la BdD.

    Or, pas du tout.
    Une erreur me disait que Userid était null.

    J'ai ensuite récupéré ID du User dans mon contrôleur pour l'envoyer à ma vue de création d'article (en remplissant un champ masqué).

    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
        public class ArticlesController : Controller
        {
    
            private readonly LeCContext _context; 
            private readonly IHttpContextAccessor _httpContextAccessor;
    
            public ArticlesController(LeCContext context, IHttpContextAccessor httpContextAccessor)
            {
                _context = context;
                _httpContextAccessor = httpContextAccessor;
            }
    
    
            public IActionResult AjoutArticle()
            {
                ViewBag.CategoryId = TrouveCategorie().Select(c => new SelectListItem { Value = c.Id.ToString(), Text = c.Nom }).ToList();
    
                //https://code-maze.com/aspnetcore-get-current-user-claims/
                string monid = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
    
                ViewData["User"] = monid;
    
                return View();
            }
    
    
            [HttpPost]
            public IActionResult AjoutArticle(Articles article)
            {
                _context.Articles.Add(article);
                _context.SaveChanges();
                return RedirectToAction("AjoutArticle");
            }
    }
    La vue :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                <div class="form-group" hidden>
                    <label asp-for="User" class="control-label">User</label>
                    <input asp-for="User" class="form-control" value=@ViewData["User"] />
                    <span asp-validation-for="User" class="text-danger "></span>
     
                </div>
    Ça ne fonctionne pas non plus.
    Erreur : UserId est Null
    L'appli va chercher cette valeur ailleurs.

    Je ne sais pas ce que je pourrais lui donner comme valeur.

    Comment faire comprendre à l'appli que 'User' de ma table 'Articles', c'est l'identifiant du User qui est actuellement connecté : un User de la table 'AspNetUsers' de Identity ?


    Depuis j'ai vu sur le net quelqu'un ne pas s’embêter avec cette relation entre les tables, et entrer l'Id de User simplement en string.

    Aucun doute qu'en 'string' ça fonctionnera, mais je trouve beaucoup plus logique que la relation soit établie entre les tables 'Articles' et 'AspNetUser'.
    Ne serait-ce que pour l'effet 'cascade', très important.
    Si un user est supprimé, tous ses articles aussi.

    En fait, je n'ai pas bien compris ce qu'est ce "public virtual ApplicationUser User" (qui permet pourtant d'établir, comme je le souhaite, une relation de clé étrangère entre mes tables)

    Toute aide sera la bienvenue,
    Merci

  2. #2
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Je crois que le problème vient du fait que "public virtual ApplicationUser User" attend un objet User.

    J'ai l'Id.

    Je recherche désespérément des infos sur "GetUserById"... que je ne trouve pas.
    Ce que je trouve :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public ApplicationUser GetUserById(int id)
    {
        return _db.Users.Find(id);
    }
    avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
            private readonly ApplicationUser _db;
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public ApplicationUser GetUserById(int id)
        {
            return _db.Users.FirstOrDefault(ApplicationUser => ApplicationUser.Id == id);
        }
    Ne fonctionne pas.
    Message : _db ne contient pas de définition pour Users

    Comme toujours (je m'habitue. Le net est monstrueusement plein de trucs pas faits pour moi, en Net 6.0. Je pourrais écrire un livre avec tous les trucs compliqués que j'ai essayé de faire fonctionner pendant des jours, avant de m'apercevoir que ce n'était pas le bon framework)

  3. #3
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 961
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 961
    Par défaut
    Citation Envoyé par AMP29
    Je crois que le problème vient du fait que "public virtual ApplicationUser User" attend un objet User.

    J'ai l'Id
    C'est en effet, là qu'est ton problème.
    La relation entre clé primaire et clé étrangère est le principe fondamental d'un base de données relationnelle.

    Mais tu as d'un coté un code C# et de l'autre une structure de base de données.
    Deux éléments distincts et EF 6 au milieu pour faire le lien.
    Sauf qu'EF n'est pas magicien, il faut lui donner quelques indications pour qu'il puisse s'en sortir.
    Cela passe par le nommage, en respectant les conventions ou par des attributs.

    De toute évidence, il te manque les bases :
    https://learn.microsoft.com/en-us/ef...gnkeyattribute

    User n'est qu'un propriété de navigation.
    Si tu ne respecte pas les conventions, EF ne sais pas qu'il doit lier tes tables, il faut lui indiquer manuellement la relation.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Articles
        {
            public long Id { get; set; }
            public string Nom { get; set; }
            public string Description { get; set; }
            public string Categorie { get; set; }
     
            [ForeignKey(nameof(User))]
            public int UserId { get; set; }
            public ApplicationUser User { get; set; }
     
        }
    Citation Envoyé par AMP29
    Message : _db ne contient pas de définition pour Users
    et
    Citation Envoyé par AMP29
    Aucun doute qu'en 'string' ça fonctionnera, mais je trouve beaucoup plus logique que la relation soit établie entre les tables 'Articles' et 'AspNetUser'.
    Si ta table est identifié en tant que "AspNetUser", il est normal que "Users" ne soit pas reconnu.
    Vérifie sous quel nom est déclaré la table de tes utilisateurs dans le contexte.

  4. #4
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Merci pour ces infos.

    Si ta table est identifié en tant que "AspNetUser", il est normal que "Users" ne soit pas reconnu.
    Vérifie sous quel nom est déclaré la table de tes utilisateurs dans le contexte.
    Je ne comprends pas bien

    ApplicationUser.cs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        public class ApplicationUser : IdentityUser
        {
            public string? Civilite { get; set; }
            public string? Nom { get; set; }
            public string? Prenom { get; set; }
            public string? Adresse { get; set; } // ? parce que Vendeur et User partage la même table 
            public string? ZipCode { get; set; }
            public string? Ville { get; set; }
            public string? Pays { get; set; }
            public virtual ICollection<Articles> Articles { get; set; }
        }
    ApplicationDbContext.cs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    namespace LeC_MVC_Auth_2024.Data
    {
        public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
     
        {
            public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
                : base(options)
            {
            }
            public DbSet<ApplicationUser> ApplicationUsers { get; set; }
        }
    }
    En fait j'ai deux contextes. Un pour Identity 'ApplicationDbContext' et un pour les tables du projet en lui-même 'LeCContext'

    J'ai modifié
    (userId est guid)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public class Articles
        {
            public long Id { get; set; }
            public string Nom { get; set; }
            public string Description { get; set; }
            public string Categorie { get; set; }
     
             public string User { get; set; }
            [ForeignKey(nameof(User))]    
            public virtual ApplicationUser ApplicationUser { get; set; }
        }
    Pour le ondelete cascade
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                  modelBuilder.Entity<Articles>()
                    .HasOne(n => n.ApplicationUser)
                    .WithMany(a => a.Articles)
                    .OnDelete(DeleteBehavior.Cascade);
    J'ai une erreur lors de l'enregistrement d'un article

    SqlException*: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Articles_ApplicationUser_User". The conflict occurred in database "CrecDB", table "dbo.ApplicationUser", column 'Id'.
    The statement has been terminated.
    J'ai deux users inscrits. Je m'aperçois qu'ils sont présents dans la table 'AspNetUsers' (avec les champs ajoutés par 'ApplicationUser'), mais sont absents de la table 'ApplicationUser' qui est vide. Est-ce normal ça ?
    Ne suis-je pas en train de me faire un sac de nœuds entre les deux contextes ?

  5. #5
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    Vérifie sous quel nom est déclaré la table de tes utilisateurs dans le contexte.
    En fait, il n'y a pas la table 'ApplicationUser' déclarée dans le contexte 'LeCContext : DbContext'
    Où je retrouve et rassemble mes tables "métier"

    Elle a été ajoutée dans la BdD par une migration sur le contexte 'ApplicationDbContext', quand j'ajoutais mes champs persos à Identity

    Je viens d'ajouter un troisième User, et toujours rien dans la table 'ApplicationUser'.
    Par contre il apparaît dans 'AspNetUsers'

  6. #6
    Membre éclairé
    Homme Profil pro
    autre
    Inscrit en
    Janvier 2015
    Messages
    212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 212
    Par défaut
    J'ai modifié la classe 'Articles'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ...
            public string? Vendeur { get; set; }
            [ForeignKey("Vendeur")]
            public ApplicationUser  ApplicationUser { get; set; }
     
        }
    Et ajouté une propriété 'Vendeur' à ma classe 'ApplicationUser'
    (inutilement je crois, car n'importe quelle propriété de la classe conviendrait pour obtenir l'Id)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ...
            public long? Vendeur { get; set; }
     
            public ICollection<Articles> Articles { get; set; }
     
        }
    J'obtiens le message d'erreur :
    SqlException*: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Articles_ApplicationUser_Vendeur".
    The conflict occurred in database "CrecDB", table "dbo.ApplicationUser", column 'Id'.
    En fait, j'ai l'impression que la relation s'établit bien, sauf que ma classe 'ApplicationUser' ne contient pas de colonne 'Id'.
    Et le code ne remonte pas jusqu'à 'IdentityUser' dont 'ApplicationUser' hérite pour le trouver.

    EDIT :
    J'ai rempli le champ 'Vendeur' avec du text, juste avant l'enregistrement, pour réussir à enregistrer un article.
    Je vois dans la BdD que, effectivement, l'application tente bien d'obtenir l'Id de la classe 'ApplicationUser'
    Nom : ApplicationUserId.png
Affichages : 75
Taille : 1,5 Ko

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 02/02/2007, 08h41
  2. nombre d'enregistrements limite dans une table sql
    Par lilou229 dans le forum Outils
    Réponses: 3
    Dernier message: 30/01/2007, 15h21
  3. Réponses: 2
    Dernier message: 12/05/2006, 12h00
  4. supprimer un enregistrement vide dans une table oracle
    Par shurized dans le forum Bases de données
    Réponses: 11
    Dernier message: 07/09/2004, 16h55
  5. URGENT - Nombre d'enregistrements différents dans une table
    Par Jeankiki dans le forum Bases de données
    Réponses: 6
    Dernier message: 11/08/2004, 15h51

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