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

  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 931
    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 931
    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 : 68
Taille : 1,5 Ko

  7. #7
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 931
    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 931
    Par défaut
    Citation Envoyé par AMP29
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    Dans ton contexte, ce qui est déclaré c'est "ApplicationUsers".
    Donc, il est logique que l'appel à _db.User ne fonctionne pas.

    Ensuite, il y a un manque de cohérence entre ton code et ce que tu dis.
    Par exemple :
    Citation Envoyé par AMP29
    (userId est guid)
    Citation Envoyé par AMP29
    public string User { get; set; }
    [ForeignKey(nameof(User))]
    public virtual ApplicationUser ApplicationUser { get; set; }
    Ta colonne est nommée "userId" mais elle s'appelle "User" dans ton code.
    Elle est de type GUID mais en String dans ton code.
    Comment veux tu qu'EF s'y retrouve.

    J'apprend ensuite que tu n'as pas un contexte mais deux et tu rajoutes encore une notion de vendeur dont tu n'a pas parlé avant.

    Citation Envoyé par AMP29
    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 ?
    En effet, tu as un sacré sac de nœud.
    C'est justement pour éviter ça que je t'avais conseillé, dans ce post, de te familiariser avec EF avant de l'intégrer dans un projet plus vaste.

    Outres tes lacune sur EF, il y a d'autres points qui ne me semblent bizarre;
    Si ta table AspNetUser contient déjà les données de ta classe ApplicationUser, alors pourquoi avoir créé deux tables ?

    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.
    Ce message apparait parce que la valeur que tu as mis dans Articles.User ne correspond à aucune valeur de la colonne Id de la table ApplicationUser.
    Ce qui est logique si la table ApplicationUser est vide.

    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'.
    Ce message apparait parce que la valeur que tu as mis dans Articles.Vendeur ne correspond à aucune valeur de la colonne Id de la table ApplicationUser.
    Tu as simplement changé le nom de la colonne mais la table ApplicationUser est toujours vide, donc tu obtiens logiquement le même message d'erreur.

  8. #8
    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
    Houla, oui, en effet, beaucoup de problèmes.
    C'est ce qui arrive quand on suit un tuto pour un problème précis, et un autre tuto pour un autre problème, et que les deux tutos ne sont pas compatibles à 100%, ou bien qu'en réalité ils présentent deux aspects d'une même solution. Ça peut créer des doublons.

    C'est justement pour éviter ça que je t'avais conseillé, dans ce post, de te familiariser avec EF avant de l'intégrer dans un projet plus vaste.
    Oui, je sais bien, mais ces problèmes je les aurais également rencontrés dans un projet test. Tant pis si ce projet se transforme en projet test. Il n'y a quasiment rien dedans pour l'instant.

    J'apprend ensuite que tu n'as pas un contexte mais deux et tu rajoutes encore une notion de vendeur dont tu n'a pas parlé avant.
    Bon, je n'ai plus qu'un seul contexte.
    'ApplicationUser' la classe d'extension de 'Identity' est à présent intégré dans mon contexte d'appli.
    Il n'y a pas réellement de notion nouvelle de 'Vendeur', puisque le vendeur est forcément un User pour pouvoir ajouter un article.
    Vendeur= User.
    Je n'ai pas de table 'Vendeur'
    C'est bien la relation 'Articles' <-> 'User'/'Vendeur' que je cherche à établir.
    Mais peut-être que je ne respecte pas une convention lorsque j'ajoute le terme 'Vendeur' pour désigner une colonne de ma table 'Articles'.

    Si ta table AspNetUser contient déjà les données de ta classe ApplicationUser, alors pourquoi avoir créé deux tables ?
    Je ne sais pas. Le tuto suivit pour étendre 'Identity' a engendré la création dans la BdD de la table 'ApplicationUser'.

    À présent, avec un seul contexte, si je tente une migration, je vois des trucs qui me semblent étranges.
    La migration tente de renommer la table 'ApplicationUser' en 'AspNetUsers' et de construire tout le modèle 'Identity' de base à partir de zéro.
    Moins les propriétés étendues que j'avais ajoutées.

    Pour appliquer cette migration, je devrais préalablement supprimer toutes les tables 'Identity' de la BdD.
    Est-ce que cela a une logique ?
    Dois-je supprimer les tables 'Identity' et appliquer cette migration ?
    Qu'est devenue l'extension de la classe 'Identity' ?

    Sinon, je repars de zéro. Je supprime toutes les migrations (du projet et de la BdD).

    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    using Microsoft.EntityFrameworkCore.Migrations;
    
    #nullable disable
    
    namespace LeC_MVC_Auth_2024.Migrations
    {
        public partial class PbVendeur6 : Migration
        {
            protected override void Up(MigrationBuilder migrationBuilder)
            {
                migrationBuilder.DropForeignKey(
                    name: "FK_Articles_ApplicationUser_ApplicationUserId",
                    table: "Articles");
    
                migrationBuilder.DropIndex(
                    name: "IX_Articles_ApplicationUserId",
                    table: "Articles");
    
                migrationBuilder.DropPrimaryKey(
                    name: "PK_ApplicationUser",
                    table: "ApplicationUser");
    
                migrationBuilder.DropColumn(
                    name: "ApplicationUserId",
                    table: "Articles");
    
                migrationBuilder.DropColumn(
                    name: "Vendeur",
                    table: "ApplicationUser");
                //*************
                migrationBuilder.RenameTable(
                    name: "ApplicationUser",
                    newName: "AspNetUsers");
    
                migrationBuilder.AlterColumn<string>(
                    name: "Vendeur",
                    table: "Articles",
                    type: "nvarchar(450)",
                    nullable: false,
                    defaultValue: "",
                    oldClrType: typeof(string),
                    oldType: "nvarchar(max)",
                    oldNullable: true);
    
                migrationBuilder.AlterColumn<string>(
                    name: "UserName",
                    table: "AspNetUsers",
                    type: "nvarchar(256)",
                    maxLength: 256,
                    nullable: true,
                    oldClrType: typeof(string),
                    oldType: "nvarchar(max)",
                    oldNullable: true);
    
                migrationBuilder.AlterColumn<string>(
                    name: "NormalizedUserName",
                    table: "AspNetUsers",
                    type: "nvarchar(256)",
                    maxLength: 256,
                    nullable: true,
                    oldClrType: typeof(string),
                    oldType: "nvarchar(max)",
                    oldNullable: true);
    
                migrationBuilder.AlterColumn<string>(
                    name: "NormalizedEmail",
                    table: "AspNetUsers",
                    type: "nvarchar(256)",
                    maxLength: 256,
                    nullable: true,
                    oldClrType: typeof(string),
                    oldType: "nvarchar(max)",
                    oldNullable: true);
    
                migrationBuilder.AlterColumn<string>(
                    name: "Email",
                    table: "AspNetUsers",
                    type: "nvarchar(256)",
                    maxLength: 256,
                    nullable: true,
                    oldClrType: typeof(string),
                    oldType: "nvarchar(max)",
                    oldNullable: true);
    
                migrationBuilder.AddPrimaryKey(
                    name: "PK_AspNetUsers",
                    table: "AspNetUsers",
                    column: "Id");
    
                migrationBuilder.CreateTable(
                    name: "AspNetRoles",
                    columns: table => new
                    {
                        Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
                        Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
                        NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
                        ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetRoles", x => x.Id);
                    });
    
                migrationBuilder.CreateTable(
                    name: "AspNetUserClaims",
                    columns: table => new
                    {
                        Id = table.Column<int>(type: "int", nullable: false)
                            .Annotation("SqlServer:Identity", "1, 1"),
                        UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
                        ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
                        ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
                        table.ForeignKey(
                            name: "FK_AspNetUserClaims_AspNetUsers_UserId",
                            column: x => x.UserId,
                            principalTable: "AspNetUsers",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                    });
    
                migrationBuilder.CreateTable(
                    name: "AspNetUserLogins",
                    columns: table => new
                    {
                        LoginProvider = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
                        ProviderKey = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
                        ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
                        UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
                        table.ForeignKey(
                            name: "FK_AspNetUserLogins_AspNetUsers_UserId",
                            column: x => x.UserId,
                            principalTable: "AspNetUsers",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                    });
    
                migrationBuilder.CreateTable(
                    name: "AspNetUserTokens",
                    columns: table => new
                    {
                        UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
                        LoginProvider = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
                        Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
                        Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
                        table.ForeignKey(
                            name: "FK_AspNetUserTokens_AspNetUsers_UserId",
                            column: x => x.UserId,
                            principalTable: "AspNetUsers",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                    });
    
                migrationBuilder.CreateTable(
                    name: "AspNetRoleClaims",
                    columns: table => new
                    {
                        Id = table.Column<int>(type: "int", nullable: false)
                            .Annotation("SqlServer:Identity", "1, 1"),
                        RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false),
                        ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
                        ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
                        table.ForeignKey(
                            name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
                            column: x => x.RoleId,
                            principalTable: "AspNetRoles",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                    });
    
                migrationBuilder.CreateTable(
                    name: "AspNetUserRoles",
                    columns: table => new
                    {
                        UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
                        RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
                    },
                    constraints: table =>
                    {
                        table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
                        table.ForeignKey(
                            name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
                            column: x => x.RoleId,
                            principalTable: "AspNetRoles",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                        table.ForeignKey(
                            name: "FK_AspNetUserRoles_AspNetUsers_UserId",
                            column: x => x.UserId,
                            principalTable: "AspNetUsers",
                            principalColumn: "Id",
                            onDelete: ReferentialAction.Cascade);
                    });
    
                migrationBuilder.CreateIndex(
                    name: "IX_Articles_Vendeur",
                    table: "Articles",
                    column: "Vendeur");
    
                migrationBuilder.CreateIndex(
                    name: "EmailIndex",
                    table: "AspNetUsers",
                    column: "NormalizedEmail");
    
                migrationBuilder.CreateIndex(
                    name: "UserNameIndex",
                    table: "AspNetUsers",
                    column: "NormalizedUserName",
                    unique: true,
                    filter: "[NormalizedUserName] IS NOT NULL");
    
                migrationBuilder.CreateIndex(
                    name: "IX_AspNetRoleClaims_RoleId",
                    table: "AspNetRoleClaims",
                    column: "RoleId");
    
                migrationBuilder.CreateIndex(
                    name: "RoleNameIndex",
                    table: "AspNetRoles",
                    column: "NormalizedName",
                    unique: true,
                    filter: "[NormalizedName] IS NOT NULL");
    
                migrationBuilder.CreateIndex(
                    name: "IX_AspNetUserClaims_UserId",
                    table: "AspNetUserClaims",
                    column: "UserId");
    
                migrationBuilder.CreateIndex(
                    name: "IX_AspNetUserLogins_UserId",
                    table: "AspNetUserLogins",
                    column: "UserId");
    
                migrationBuilder.CreateIndex(
                    name: "IX_AspNetUserRoles_RoleId",
                    table: "AspNetUserRoles",
                    column: "RoleId");
    
                migrationBuilder.AddForeignKey(
                    name: "FK_Articles_AspNetUsers_Vendeur",
                    table: "Articles",
                    column: "Vendeur",
                    principalTable: "AspNetUsers",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
    
            }
    
            protected override void Down(MigrationBuilder migrationBuilder)
            {
                ...
    
            }
        }
    }
    Mon contexte :

    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
     
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
     
     
    namespace LeC_MVC_Auth_2024.Models
    {
        // FLUENT API
     
        public class LeCContext : IdentityDbContext<ApplicationUser>
     
     
        {
     
            //public DbSet<ApplicationUser> ApplicationUsers { get; set; }
     
            public DbSet<Articles> Articles { get; set; }
     
            public LeCContext(DbContextOptions<LeCContext> options) : base(options)
            {
            }
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                base.OnConfiguring(optionsBuilder);
            }
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
     
     
     
     
                #region --- A R T I C L E S ---
                modelBuilder.Entity<Articles>().HasKey(d => d.Id);
                modelBuilder.Entity<Articles>().Property(d => d.Nom).IsRequired();
                modelBuilder.Entity<Articles>().Property(d => d.Description).IsRequired();
                modelBuilder.Entity<Articles>().Property(d => d.ArticleRefVendeur).IsRequired();
                modelBuilder.Entity<Articles>().Property(d => d.Categorie).IsRequired();
                modelBuilder.Entity<Articles>().Property(d => d.Matieres).IsRequired();
                ... 
                ...
     
                modelBuilder.Entity<Articles>()
                    .HasOne(n => n.ApplicationUser)
                    .WithMany(a => a.Articles)
                    .OnDelete(DeleteBehavior.Cascade);
     
                #endregion
     
            }
     
        }
    }
    ApplicationUser :

    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
     
    using Microsoft.AspNetCore.Identity;
    using System.ComponentModel.DataAnnotations.Schema;
     
    namespace LeC_MVC_Auth_2024.Models
    {
        public class ApplicationUser : IdentityUser
        {
            public string? Civilite { get; set; }
            public string? Nom { get; set; }
            public string? Prenom { get; set; }
            public string? Adresse { get; set; } 
            public string? ZipCode { get; set; }
            public string? Ville { get; set; }
            public string? Pays { get; set; }
            public ICollection<Articles> Articles { get; set; }
        }
    }
    Classe 'Articles'
    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
     
    using Microsoft.AspNetCore.Mvc.Rendering;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
     
    namespace LeC_MVC_Auth_2024.Models
    {
        [Table("Articles")]
        public class Articles
        {
     
            // Description générale
            public long Id { get; set; }
            public string Nom { get; set; }
            public string Description { get; set; }
            public string ArticleRefVendeur { get; set; }
            public string Categorie { get; set; }
            ...
            ...
     
            public string? Vendeur { get; set; }
            [ForeignKey("Vendeur")]
            public virtual ApplicationUser ApplicationUser { get; set; }
        }
    }

  9. #9
    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 repars de zéro.
    J'ai supprimé la BdD.
    Effectué la première migration.

    Je n'ai plus que ce problème de relation entre les classe 'Articles' et 'AspNetUsers' à gérer.
    (la table 'ApplicationUser' n'existe plus dans la nouvelle BdD)

  10. #10
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 931
    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 931
    Par défaut
    La migration nécessite un contexte.
    Tu as bien dû t'apercevoir que lorsque tu en avais deux, la commande Add-Migration te demandait de préciser le contexte.

    Pour supprimer l'un des contexte, je suppose que tu as déplacé la table des Users.
    Et forcément, sur le contexte restant, vu qu'elle n'existait pas, il tente de la créer.
    Sauf qu'il se rend compte qu'en fait la table existe déjà en base et là, il sait pas trop quoi faire, d'où les modifications étranges.

    Pour moi, le plus simple est de supprimer ta base et les fichiers de migrations pour repartir de zéro.

    Je pense que tu as deux tables "User" car le comportement par défaut est de créer une table par classe déclarée dans le contexte.

    Je n'ai jamais utilisé l'extension Identity, alors ceci n'est que de la théorie.
    Mais, je soupçonne que AspNetUsers est déclarée dans IdentityDbContext et que tu as déclaré ApplicationUser dans LeCContext.
    Il doit y avoir un truc dans ton tuto qui explique comment n'obtenir qu'une seule table ou comment répartir les colonnes sur les deux tables.

    Si ça peux t'aider j'ai eu un cas où j'avais les classes TextShape et GeometricShape héritant toutes deux d'une classe Shape.
    Mon objectif était d'avoir des données commune dans la table Shape et des données spécifique dans les tables TextShape et GeometricShape.

    J'ai du passer par la méthode UseTptMappingStrategy pour avoir une structure où l'id déclaré dans TextShape et GeometricShape soit PK dans ces tables et FK de la table Shape.
    Je n'en suis pas certain mais ta structure avec deux table semble correspondre à ce schéma.

    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
    [Table("Shape")]
    public class Shape
    {
            [Key]
            [Required]
            [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public Guid Id { get; set; }
     
            [Required]
            [MaxLength(50)]
            public string Name { get; set; } = null!;
     
            [Required]
            public int Top { get; set; } 
     
            [Required]
            public int Left { get; set; }
     
            [Required]
            public int Width { get; set; }
     
            [Required]
            public int Height { get; set; }
    }
     
    [Table("GeometricShape")]
    public class GeometricShape : DataShape
    {
            [DefaultValue("000000")]
            public string HexadecimalColor { get; set; }
    }
    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
    public class DefaultContext : DbContext
    {
            public DefaultContext()
            {
            }
            public DefaultContext(DbContextOptions<DefaultContext> options) : base(options)
            {
     
            }
     
            public DbSet<Shape> Shapes { get; set; }
            public DbSet<TextShape> TextShapes { get; set; }
            public DbSet<GeometricShape> GeometricShapes { get; set; }
     
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Shape>().UseTptMappingStrategy();
     
                base.OnModelCreating(modelBuilder);
            }
     
    }

  11. #11
    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
    Tu as bien dû t'apercevoir que lorsque tu en avais deux, la commande Add-Migration te demandait de préciser le contexte.
    Oui ! Je jonglais entre les contextes. C'était pénible, mais je croyais que c'était normal.

    Pour supprimer l'un des contexte, je suppose que tu as déplacé la table des Users.
    Et forcément, sur le contexte restant, vu qu'elle n'existait pas, il tente de la créer.
    Sauf qu'il se rend compte qu'en fait la table existe déjà en base et là, il sait pas trop quoi faire, d'où les modifications étranges.
    Tout à fait ! Je comprends.

    Pour moi, le plus simple est de supprimer ta base et les fichiers de migrations pour repartir de zéro.
    Oh oui ! C'est fait

    Je pense que tu as deux tables "User" car le comportement par défaut est de créer une table par classe déclarée dans le contexte.
    Je comprends. Je n'en ai plus qu'une à présent. Celle de 'Identity', 'AspNetUsers' avec les colonnes de mon extension (finalement, ça a correctement migré)
    Je me retrouve dans une situation claire maintenant.

    J'ai ajouté un nouvel User. Il est bien inscrit dans 'AspNetUsers'.
    Par contre pour ajouter un article, il n'y a toujours pas de relation établie entre 'Articles' et 'AspNetUsers'.
    Mais c'est peut-être maintenant juste un problème de convention ou de clé explicite.
    J'avoue que même en lisant les infos Microsoft, en suivant le lien que tu m'avais donné, je n'y comprends pas grand chose.
    La traduction n'aide pas, non plus.

    Je vais regarder 'UseTptMappingStrategy'.
    Merci. J'aime bien découvrir de nouvelles méthodes.

  12. #12
    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 porte tous mes efforts sur la déclaration explicite de clé étrangère dans ma classe 'Articles'.
    Je procède à des essais, sans résultat.

    J'ai essayé de pointer 'IdentityUser' plutôt que 'ApplicationUser', et pour la migration j'ai ce message d'erreur :

    Une clé ne peut pas être configurée sur « ApplicationUser » car il s'agit d'un type dérivé.
    La clé doit être configurée sur le type racine « IdentityUser ».
    Si vous n'aviez pas prévu d'inclure « IdentityUser » dans le modèle, assurez-vous qu'il n'est pas
    référencé par une propriété DbSet sur votre contexte, référencé dans un appel de configuration à
    ModelBuilder ou référencé à partir d'une navigation sur un type inclus dans le modèle.
    C'est intéressant, sauf que c'est tout le contraire que j'essayais de faire :

    Classe 'Articles' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
            ...
            [ForeignKey("UserName")]
            public IdentityUser UserNameId { get; set; }
        }
    'IdentityUser' n'est pas référencé par une propriété DbSet sur mon contexte,
    ni référencé dans un appel de configuration à ModelBuilder
    Par contre je ne sais pas ce que veux dire : référencé à partir d'une navigation sur un type inclus dans le modèle

    Je retiens l'info que 'ApplicationUser' ne peut pas établir une relation de clé étrangère.

    Je suis bien dans la mouise, si je ne peux utiliser ni 'IdentityUser' ni 'ApplicationUser' pour la clé étrangère.

  13. #13
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 931
    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 931
    Par défaut
    Donc si j'ai bien tout suivi, tu as désormais une unique table AspNetUsers contenant à la fois les colonnes de la classe IdentityUser et celle de la classe ApplicationUser que tu as fait hériter de IdentityUser.
    Si tu n'as pas changé la clé de IdentityUser la PK de la la table AspNetUsers devrait être nommée "Id".

    Donc pour suivre les convention et mettre toutes les chances de ton coté pour que EF fasse la relation correctement, je pense que tu devrais déclarer la classe Articles de cette manière :
    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
    namespace LeC_MVC_Auth_2024.Models
    {
        [Table("Articles")]
        public class Articles
        {
            [Required]
            public string Nom { get; set; }
     
            [Required]
            public string Description { get; set; }
     
            ...
     
            [Required]
            [ForeignKey(nameof(ApplicationUser))]
            public string ApplicationUserId { get; set; }
            public ApplicationUser ApplicationUser { get; set; }
        }
    }
    Dans cet exemple, le nom de la propriété donnée pour la FK respecte la convention de nommage.
    Alors l'attribut [ForeignKey] n'est probablement pas nécessaire mais ça ne coute rien de le rajouter.

    Le fait de déclarer cette propriété [Required] devrait également provoquer le Delete en cascade que tu souahaites.
    C'est le comportement par défaut : https://learn.microsoft.com/en-us/ef...aviorattribute

    Mais tu peux aussi le forcer avec [DeleteBehavior(DeleteBehavior.Cascade)].

    De fait, avec ces attributs, tu devrais plus avoir besoin des lignes suivantes dans ton contexte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    modelBuilder.Entity<Articles>().HasKey(d => d.Id);
    modelBuilder.Entity<Articles>().Property(d => d.Nom).IsRequired();
    modelBuilder.Entity<Articles>().Property(d => d.Description).IsRequired();
    modelBuilder.Entity<Articles>().Property(d => d.ArticleRefVendeur).IsRequired();
    modelBuilder.Entity<Articles>().Property(d => d.Categorie).IsRequired();
    modelBuilder.Entity<Articles>().Property(d => d.Matieres).IsRequired();
     
     
    modelBuilder.Entity<Articles>()
            .HasOne(n => n.ApplicationUser)
            .WithMany(a => a.Articles)
            .OnDelete(DeleteBehavior.Cascade);

  14. #14
    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
    Donc si j'ai bien tout suivi, tu as désormais une unique table AspNetUsers contenant à la fois les colonnes de la classe IdentityUser et celle de la classe ApplicationUser que tu as fait hériter de IdentityUser.
    Si tu n'as pas changé la clé de IdentityUser la PK de la la table AspNetUsers devrait être nommée "Id".
    C'est correct.

    Dans cet exemple, le nom de la propriété donnée pour la FK respecte la convention de nommage.
    Alors l'attribut [ForeignKey] n'est probablement pas nécessaire mais ça ne coute rien de le rajouter.
    Oui, tu as raison.
    Je suis tombé sur une vidéo 'parfaite' qui traite de cette question, précisément pour mon environnement :



    L'unique chose à écrire dans la classe qui reçoit l'objet User est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
            ...
            [ValidateNever]
            public IdentityUser User { get; set; }
            public string IdentityUserId { get; set; }
    }
    Rien dans le contexte. Tu as raison.

    EF se charge de tout.

    J'ai testé cela avec un projet test (oui, je sais ) créé à partir de zéro.
    Et ça fonctionne super.

    Cela ajoute dans le contrôlleur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
                ViewData["IdentityUserId"] = new SelectList(_context.Users, "Id", "Id");
    et dans la View :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                <div class="form-group">
                    <label asp-for="IdentityUserId" class="control-label"></label>
                    <select asp-for="IdentityUserId" class="form-control" asp-items="ViewBag.IdentityUserId"></select>
                </div>
    La relation de clé étrangère est établie entre ma table 'Articles' et 'AspNetUsers'.

    Le fait de déclarer cette propriété [Required] devrait également provoquer le Delete en cascade que tu souahaites.
    C'est le comportement par défaut : https://learn.microsoft.com/en-us/ef...aviorattribute
    Oui, en effet, le delete en cascade est inscrit par défaut.

    Le seul truc qui n'est pas comme chez moi dans cette vidéo c'est qu'elle montre le fonctionnement sans l'extension 'ApplicationUser' sur 'Identity'.

    Je suis maintenant en train d'essayer de le faire fonctionner en ajoutant l'extension 'ApplicationUser'.

    Par ailleurs, il y avait certainement des aspects qui entravaient mes tests (notamment de migration et de update-database).
    Si la table n'est pas vide, cela peut échouer. Pffff !
    Et j'avais souvent des valeurs dans ma table 'Articles'.
    C'est pas les messages d'erreur ésotériques qui pouvaient me le dire... re Pffff !
    Et puis ma View Create était une View générée par Razor très tôt au début du projet, j'imagine qu'elle aurait dû être régénérée.
    J'y avais fait beaucoup de modifications.
    Dans le projet test j'ai fait générer controller (CRUD total) et View par Razor, il savait quoi y mettre pour que ça fonctionne.

    Bref, il vaut mieux s'assurer des fonctionnalités de base avant de se lancer dans certaines finitions de la présentation.

    Je teste avec 'ApplicationUser'
    (Mon projet test va bientôt devenir plus avancé que mon projet principal si ça continue )

  15. #15
    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
    Cela fonctionne avec l'extension 'ApplicationUser' sur 'Identity'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
            ...
     
            [ValidateNever]
            public ApplicationUser User { get; set; }
            public string ApplicationUserId { get; set; }
        }
    Conseil pour l'extension : Faire une recherche Ctrl+F sur 'IdentityUser' pour tous les remplacer par 'ApplicationUser'.
    Et 'IdentityUserId' par 'ApplicationUserId'. Il y en a partout.

    Il y a peut-être également un ordre à suivre.
    D'abord créé la relation, puis appliquer l'extension.
    Je ne sais pas...


    Merci Popo !

+ 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