Bonjour,

Je travaille sur un projet web en C# .Net sous VB 2015. J'utilise localDB avec une BDD en Code First.

J'ai un soucis d'update de données sur une table. Je vous montre la table et le code et je vous en dit plus :

La table :
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
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
 
// Association des produits avec les lots
namespace Akebia.Models
{
    public class LotProduit
    {
        [Column(Order = 0), Key, Required]
        public int LotID { get; set; }
 
        [Required]
        [ForeignKey("LotID")]
        public virtual Lot lot { get; set; }
 
        [Column(Order = 1), Key, Required]
        public long produitID { get; set; }
 
        [Required]
        [ForeignKey("produitID")]
        public virtual Produit produit { get; set; }
 
        public int quantite { get; set; }
 
    }
}
Je précise que les PK/FK ne me posent pas (plus) de problème, c'est "quantité" qui m'en pose. Voilà comment je le modifie :
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
public void UpdateItem(int lotID, int produitID, int quantite)
        {
            LotProduit association = _db.LotProduit.FirstOrDefault(c =>
                c.lot.LotID == lotID && c.produit.produitID == produitID);
            try
            {
 
                if (association != null)
                {
                    association.quantite = quantite;
                    _db.SaveChanges();
                }
            }
            catch (Exception exp)
            {
                throw new Exception("ERROR: Unable to Update LotProduit Item - "+quantite+" - " + association.quantite + " - " + exp.Message.ToString(), exp);
            }
        }
J'ai passé mes paramètres dans la chaine du message d'erreur pour m'assurer qu'ils étaient bons... Et ils le sont, ils correspondent toujours à ce que je souhaite.
Cependant, les catch font tout de même leur office :
Une exception de type 'System.Exception' s'est produite dans Akebia.dll mais n'a pas été gérée dans le code utilisateur

Informations supplémentaires : ERROR: Unable to Update LotProduit Database - ERROR: Unable to Update LotProduit Item - 5 - 5 - Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
J'ai réévalué l'expression de l'exception dans VS et voilà le résultat :
+ ((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors '((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors' a levé une exception de type 'System.InvalidCastException' System.Collections.Generic.IEnumerable<System.Data.Entity.Validation.DbEntityValidationResult> {System. }
Donc selon lui, lors de mon _db.SaveChanges() je soulève une exception InvalidCastException qui indique donc que je passerait un mauvais type de paramètre dans ma BDD ou que je ferais appel à un Cast implicite non géré. Il ne s'agit pas d'un OverFlow.

Seulement voilà, j'ai essayé de caster, en int16, en int32, j'ai mis des entiers en dur dans le code pour voir, j'ai mis "++" et autres trucs débiles... Et rien n'y fait !
De plus vous pouvez clairement voir dans le code plus haut que je met bien un int dans un int et que saperlipopette ça ne devrait pas le choquer !

Bref, il y a plus étrange :
A la création d'une entité LotProduit, le paramètre quantite est égal à 1. Lorsque je procède à l'ajout d'un nouveau produit dans mon lot, je vérifie que l'association LotProduit n'existe pas déjà, et si elle existe je ne la créer pas mais j'incrémente ce paramètre quantité (++).
Et ceci fonctionne à merveille !

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
public void AddToLot(int produitID, int lotID)
        {
            // Le produit et le lot qui doivent s'associer
            Produit produit = _db.Produit.FirstOrDefault(c => c.produitID == produitID);
            Lot lot = _db.Lot.FirstOrDefault(c => c.LotID == lotID);
 
            // Recherche du lot (null si introuvable)
            LotProduit association = _db.LotProduit.FirstOrDefault(c => 
                c.LotID == lotID && c.produitID == produitID);
 
            // Si le lot existe
            if (lot != null)
            {
                // Si le produit n'est pas associé au lot
                if (association == null)
                {
                    LotProduit lotNouveau = new LotProduit
                    {
                        lot = lot,
                        LotID = lot.LotID,
                        produit = produit,
                        produitID = produit.produitID,
                        quantite = 1,
                    };
                    _db.LotProduit.Add(lotNouveau);
                }
                else // Le produit est déjà associé lot
                {
                    association.quantite++;
                }
            }
 
            _db.SaveChanges();
        }
Ce code est placé dans la même classe et utilise la même variable de classe _db :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
private ProduitContext _db = new ProduitContext();
Pourquoi ce qui fonctionne pour l'un ne fonctionne pas pour l'autre?!

Et enfin, le plus incroyable pour la fin :
Le paramètre que je passe dans ma méthode UpdateItem est lu dans une TextBox. La méthode UpdateItem est appelée (à la suite de 2 autres) à chaque fois que j'appuie sur un bouton "actualiser".
Les méthodes lisent les paramètres dont UpdateItem a besoin (dont quantité), et appellent UpdateItem dans tous les cas SAUF si quantite < 1 (auquel cas c'est la suppression de l'item qui entre en jeu, et cette méthode fonctionne très bien).

Or, lorsque je fais appel à actualiser et que donc j'appelle la méthode UpdateItem sans modifier la quantité dans ma TextBox, alors la méthode ne plante pas ! Y comprit les produits dont la quantité lue dans la TextBox est supérieure à 1 (incrémentés par la méthode AddToLot) ! Peut-être que cela est géré en coulisses par SaveChanges qui détecte qu'il n'y a aucun changement?

Le problème ne survient que lorsqu'il y a modification de LotProduit.quantite... Et uniquement dans la méthode UpdateItem.

Vu que mes autres méthodes fonctionnent parfaitement, et que je ne vois pas de différence avec celle-ci, et vu que j'y suis depuis quelques heures déjà, j'espère que l'un de vous aura une idée brillante.