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 :

Suppression d'un utilisateur, erreur de Cascade Delete


Sujet :

ASP.NET

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

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 228
    Par défaut Suppression d'un utilisateur, erreur de Cascade Delete
    J'utilise une messagerie d'utilisateur à utilisateur.
    Voici sa classe :

    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
     
        public class MessagesModel
        {
            public long Id { get; set; }
            public ApplicationUser UserExp { get; set; }
            public ApplicationUser UserDest { get; set; }
            public Articles Article { get; set; }
     
            public string Message { get; set; }
            public messageStatus Status { get; set; }
            public DateTime Created_at { get; set; }
            public string Topic { get; set; }
            public bool NewMsg { get; set; }
            public bool NewMsg_Exp { get; set; }
            public bool NewMsg_Dest { get; set; }
            public int Offre { get; set; }
            public OfferStatus OffreStatus { get; set; }
     
            public enum messageStatus
            {
                Sent,
                Delivered
            }
            public enum OfferStatus
            {
                None,
                Sent,
                Accepted,
                Denied,
                Cancelled,
                Expired
            }
            public MessagesModel()
            {
                Status = messageStatus.Sent;
                OffreStatus = OfferStatus.None;
            }
        }
    Cela génère 3 clés étrangères dans la table.
    Extrait du fichier de migration (Code First) :

    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
     
        constraints: table =>
         {
         	table.PrimaryKey("PK_Messages", x => x.Id);
         	table.ForeignKey(
         		name: "FK_Messages_Articles_ArticleId",
         		column: x => x.ArticleId,
         		principalTable: "Articles",
         		principalColumn: "Id",
         		onDelete: ReferentialAction.Cascade);
         	table.ForeignKey(
         		name: "FK_Messages_AspNetUsers_User_DestId",
         		column: x => x.User_DestId,
         		principalTable: "AspNetUsers",
         		principalColumn: "Id");
         	table.ForeignKey(
         		name: "FK_Messages_AspNetUsers_User_ExpId",
         		column: x => x.User_ExpId,
         		principalTable: "AspNetUsers",
         		principalColumn: "Id");
         });

    Quand je supprime un utilisateur j'obtiens cette erreur :
    SET NOCOUNT ON; DELETE FROM [AspNetUsers] WHERE [Id] = @p0 AND [ConcurrencyStamp] = @p1; SELECT @@ROWCOUNT;
    Microsoft.EntityFrameworkCore.Update: Error: An exception occurred in
    the database while saving changes for context type
    'LeC_MVC_Auth_2024.Models.LeCContext'.
    Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred
    while saving the entity changes. See the inner exception for details.
    ---> Microsoft.Data.SqlClient.SqlException (0x80131904): The DELETE statement conflicted with the REFERENCE constraint
    "FK_Messages_AspNetUsers_UserDestId". The conflict occurred in
    database "CrecDB", table "dbo.Messages", column 'UserDestId'
    .
    La suppression en cascade fonctionne sur tous les 'articles' que possède l'utilisateur. Cela fonctionne bien pour toutes les autres tables (Panier, Favoris, Articles) tant que l'utilisateur n'a pas de message dans la messagerie.

    Dans ce cas précis, je ne sais pas si cette erreur survient au moment de la suppression de l'article, sujet du message, ou à celui de la suppression de l'utilisateur lui-même.
    J'ai lu beaucoup sur la suppression en cascade, mais je ne comprends pas toujours ce que j'ai lu, et si cela peut s'appliquer à mon problème.

    J'ai lu des choses sur ".WillCascadeOnDelete(false);" mais cette option n'existe pas pour moi.

    Extrait de mon 'OnModelCreating' (qui ne comporte quasiment rien) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #region --- M E S S A G E S   ---
    modelBuilder.Entity<MessagesModel>().HasKey(d => d.Id);
    modelBuilder.Entity<MessagesModel>().Property(d => d.Offre).HasDefaultValue(0);
    #endregion
    À ce point, je ne vois que deux solutions
    - Empêcher de créer des clés étrangères pour "UserExp" et "UserDest" (j'ai besoin que cela reste 'ApplicationUser')
    - Faire en sorte que la suppression en cascade ne se produise pas pour ces deux clés étrangères

    Merci pour votre aide.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 620
    Par défaut
    Le message indique clairement que c'est à la suppression des messages (vu que l'erreur se produit pour la table Messages.
    L'erreur se produit ici quand l'utilisateur est destinataire d'un message (UserDestId)

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

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 228
    Par défaut
    Bonjour,
    Je suis entrain de configurer mon appli pour la suppression logicielle, plutôt que définitive.
    En interdisant donc le delete cascading.

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 620
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 620
    Par défaut
    Je crois qu'il te manquait les "on delete cascade" au niveau des clés étrangères (qui aurait pour effet de supprimer les enregistrements si le destinataire ou l'expéditeur est supprimé; à voir si c'est le besoin/résultat voulu).
    Tu as des autres méthodes que cascade, tu as "NO ACTION" (tu ne peux pas supprimer l'utilisateur, tant qu'il y a une référence à cet utilisateur dans une table liée (par défaut), SET NULL où la référence de l'utilisateur supprimé est mise à NULL, SET DEFAULT, met la valeur par défaut (qui doit être définie)

  5. #5
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 816
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 816
    Par défaut
    Hello,

    Dans une messagerie, si un utilisateur supprime son compte, on souhaite souvent garder les messages pour l'interlocuteur restant. L'expéditeur devient "Utilisateur Supprimé" (NULL).

    Pour cela, il faut configurer le comportement ClientSetNull. Cela signifie que EF Core va mettre à jour les messages pour mettre NULL dans les colonnes UserExpId ou UserDestId avant de supprimer l'utilisateur.

    Pré-requis : Les relations doivent être optionnelles (nullable). Dans votre classe MessagesModel, assurez-vous que les propriétés de navigation permettent le null.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

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

    Informations professionnelles :
    Activité : autre

    Informations forums :
    Inscription : Janvier 2015
    Messages : 228
    Par défaut
    Merci @fred1599 et @umfred pour ces informations.

    La "suppression" par défaut sera une suppression logicielle.
    Vous et d'autres, m'avez convaincu, car une suppression définitive sur des centaines voire des milliers d'enregistrement (messagerie, images, notamment) risque d'être lourde à gérer pour la BdD (en production, avec des milliers d'utilisateurs).
    Et puis, les pratiques métier recommandent, voire obligent parfois, à conserver certaines informations en BdD.

    Par ailleurs, je n'ai pas réussi à régler précisément le delete cascading pour chaque clé étrangère.

    Dans ma classe "Messages" c'est ASP NET (Code First) lui-même qui a réglé le Delete Cascade sur le champ 'Article' mais pas sur 'UserExp' et 'UserDest'.
    J'ai essayé de trouver comment appliquer les options que vous mentionnez (ClientSetNull, No action...) pour une FK particulière sans toucher aux autres, mais sans y parvenir.
    Cela ne se règle pas au niveau du :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    modelBuilder.Entity<MessagesModel>().options etc...
    Je ne comprends pas comment ASP NET choisi pour les uns et pas pour les autres.
    Alors, dernièrement, j'ai opté pour la solution radicale et empêché tous les Delete Cascade avec ce bout de code dans l'Api Fluent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                foreach(var foreignKey in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
                {
                    foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
                }
    Cependant, je souhaiterais quand même profiter des deux options, Suppression logicielle (par défaut) et Suppression définitive (choix supplémentaire de Admin, si nécessaire).

Discussions similaires

  1. Erreur lors du delete en cascade
    Par nean_j dans le forum JPA
    Réponses: 2
    Dernier message: 15/10/2008, 13h20
  2. [ EJB ] [JBoss ] [ XDoclet ] probleme avec cascade-delete
    Par Houbbba dans le forum Wildfly/JBoss
    Réponses: 4
    Dernier message: 03/05/2006, 11h05
  3. erreur de syntaxe DELETE multi-tables
    Par yayacameleon dans le forum Requêtes
    Réponses: 7
    Dernier message: 12/04/2006, 12h34
  4. Erreur de syntaxe: DELETE
    Par Pigoulou dans le forum Requêtes
    Réponses: 2
    Dernier message: 19/01/2006, 07h51
  5. [EJB2.1 Entity] [XDOCLET]Cascade delete
    Par SEMPERE Benjamin dans le forum Java EE
    Réponses: 3
    Dernier message: 23/02/2005, 10h29

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