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

C# Discussion :

requête (mySql sous c#) pour plusieurs utilisateurs en même temps [Débutant]


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    316
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2010
    Messages : 316
    Par défaut requête (mySql sous c#) pour plusieurs utilisateurs en même temps
    Bonjour,

    Mon application Web donne un code de promo, par courriel, aux utilisateurs qui remplissent le formulaire.

    Ce code est unique, utilisable une seule fois par l'utilisateur. Il est stocké dans une base de données (BDD).

    Chaque fois qu'un utilisateur remplit le formulaire au 1er écran, l'application connecte à la bdd, et obtient la valeur du 1er champ, "cd_promo", du PREMIER ENGREGISTREMENT/ PREMIERE LIGNE de la table "client".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string mySqlReq = "SELECT cd_promo FROM client LIMIT 1";
    Une fois que le code a été envoyé, par courriel, à l'utilisateur, le programme supprime le code dans la BDD, dans le 2e écran.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string mySqlReqSupr = "DELETE FROM  client WHERE cd_promo=@CodeEnvoye;";
    Du coup, 2e utilisateur peut obtenir un autre code.

    Ça marche très bien. Par contre, j'ai une idée qui peut causer beaucoup de problèmes*:

    Mon problème est le suivant*: si par hasard, en même temps, 2 utilisateurs remplissent le formulaire au 1er écran, j'imagine qu'ils vont évidemment obtenir, tous les deux, le même code [QUI SE TROUVE DANS PREMIER ENREGISTREMENT] !!! Il faut éviter cela*:

    Autrement dit, il ne faut pas qu'ils reçoivent le même code qui se trouve dans 1er enregistrement.

    En plus de cela, j'imagine une autre chose qui irait se produire au 2e écran*: 1er utilisateur clique sur le bouton, l'email part dans sa boite de courriel et ce code est supprimé par la requête. Ensuite, 2er utilisateur clique sur le bouton, l'email part avec le même code de promo dans son boite de courriel et le code n'excite plus (puisque le 1er l'a supprimé avant lui) alors l'application peut afficher un message d'erreur.


    Alors que je dois faire pour que ma requête (mySqlReq) ne donne pas la même valeur s'il y a plusieurs utilisateurs remplissent en même temps le formulaire. En plus, ils ont évidemment le droit de remplir le formulaire en même temps, et nous n'avons pas le droit de les empêcher.

    Merci et bonne journée

  2. #2
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    Une solution peut-être envisageable pour SQL Server serait d'ajouter un champ CDFLAG à la table (champ valant 0 lorsque le code est dispo et 1 lorsqu'il est vérouillé) et de de faire un ExecuteQuery avec :
    "UPDATE client SET CDFLAG=1 WHERE CDFLAG=0 LIMIT 1 OUTPUT cd_Promo"

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    316
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2010
    Messages : 316
    Par défaut
    Bonjour Graffito,

    Est-ce que votre exemple marche avec MySql server ?
    Si oui, comment je peux faire un champ CDFLAG dans MySql ?

    J'ai regardé dans ma table, il n'y pas de de type 'CDFLAG'. Il y a possibilité de 39 types, mais pas CDFLAG :

    voici les posibilités de type : TINYINT ; SMALLINT ; MEDIUMINT ; INT ; BIGINT ; DECIMAL ; FLOAT ; DOUBLE ; REAL ; BIT ; BOOL ; SERIAL ; DATE ; DATETIME ; TIMESTAMP ; TIME ; YEAR ; CHAR ; VARCHAR ; TINYTEXT ; TEXT ; MEDIUMTEXT ; LONGTEXT ; BINARY ; VARBINARY ; TINYBLOB ; MEDIUMBLOB ; BLOB ; LONGBLOB ; ENUM ; SET ; GEOMETRY ; POINT ; LINESTRING ; POLYGON ; MULTIPOINT ; MULTILINESTRING ; MULTIPOLYGON et EOMETRYCOLLECTION


    Je pense que j'ai trouvé la solution :
    faire une requête sql avec l’ordre aléatoire via Order by Rand ()
    Donc s'il y a plusieurs consultations de formulaire en même temps par différents utilisateurs, le risque d'avoir plusieurs mêmes codes est très minimum...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string sqlBDD = "SELECT cd_promo FROM client order by rand() LIMIT 1";
    Qu'en vous dites sur cette solution?

  4. #4
    Membre émérite Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Par défaut
    Salut,
    C'est à ça que servent les transactions.

  5. #5
    Expert confirmé Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Par défaut
    CDFLAG était juste un nom pour un nouveau champ de type de INT (ou SMALLINT ou TINYINT) à ajouter à la table.

    "OUTPUT" n'existe pas en MySql.

    Les solutions seront donc plus complexes; En voici une évitant de recourir aux transactions :
    - on fait un SELECT ... LIMIT 1
    - on récupère ainsi un code promo et on l'inverse,
    - on fait un UPDATE ... SET codePromo=Code_promo_inversé WHERE codePromo=CodePromo_récupéré
    - on teste le retour de l'update pour voir le nombre d'enregistrements mis à jour,
    - si ce nombre est nul, on reboucle sur le SELECT.

    Qu'en vous dites sur cette solution?
    Non, noon, noooon
    On ne peut pas accepter une bug identifiée quelque soit son degré de probabilité. Si on tolère de telles dérives à tous les niveaux d'un projet, on va additioner les probabilités, et au final bonjour les dégats ...

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    316
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2010
    Messages : 316
    Par défaut
    Citation Envoyé par Graffito Voir le message
    CDFLAG était juste un nom pour un nouveau champ de type de INT (ou SMALLINT ou TINYINT) à ajouter à la table.

    "OUTPUT" n'existe pas en MySql.

    Les solutions seront donc plus complexes; En voici une évitant de recourir aux transactions :
    - on fait un SELECT ... LIMIT 1
    - on récupère ainsi un code promo et on l'inverse,
    - on fait un UPDATE ... SET codePromo=Code_promo_inversé WHERE codePromo=CodePromo_récupéré
    - on teste le retour de l'update pour voir le nombre d'enregistrements mis à jour,
    - si ce nombre est nul, on reboucle sur le SELECT.
    Merci pour vos explications, Graffito
    --- Alors j'ai ajouter une autre champs "cd_promo_vide" [ varchar(5) DEFAULT NULL]

    --- Je fait ma requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string sqlBDD = "SELECT cd_promo FROM client WHERE "cd_promo_vide"  IS NULL order by rand() LIMIT 1;
    Donc j'ai choisi un engresistrement par hasard du champ cd_promo et le champ cd_promo_vide est vide

    --- En fait, il faut faire une changement...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE client SET code_test_vide = cd_promo WHERE  cd_promo = vChiffre;
    ou bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE client SET code_test_vide = vChiffre WHERE  cd_promo = vChiffre;
    ou bien mieux encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE client SET code_test_vide = '1' WHERE  cd_promo = vChiffre;
    N'est ce pas ?
    Par contre, je ne sais pas comment je peux faire 2 requêtes en même temps dans une seule connexion avec une variable locale "vChiffre" ?
    Il faut 2 connexions ?
    Voici le code :
    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
    string mySqlReq = "SELECT cd_promo FROM client WHERE cd_promo_vide IS NULL  order by rand() LIMIT 1";
     
    MySqlCommand cmdCDpomo = new MySqlCommand(mySqlReq, connCDpomo);
     
    MySqlDataReader myReaderCDpomo;
     
    myReaderCDpomo = cmdCDpomo.ExecuteReader();
    string vChiffre;
     // Always call Read before accessing data.
    while (myReaderCDpomo.Read()) 
    	{
     
    	vChiffre = myReaderCDpomo.GetString(0);
     
    	ecranApageState.CodePromo = vChiffre;
     
    	// Faut il faire la 2e requête ici pour récupérer la valeur de vChiffre?
    	// il faut fermer la connections? donc il faut que je sorte de ma boucle while mais dans ce cas là, je ne peux pas récupérer la valeur de vChiffre
    	}
     
    // always call Close when done reading.
    myReaderCDpomo.Close();
    // Close the connection when done with it.
    connCDpomo.Close();
    Bonne soirée

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    316
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2010
    Messages : 316
    Par défaut
    Citation Envoyé par ctxnop Voir le message
    Salut,
    C'est à ça que servent les transactions.
    C'est très intéressant, cet article...

    par contre, on ne peut pas appliquer, si je ne m'en trompe pas, dans mon cas puisqu'il s'agit d'une action qui commence dans un écran et qui se termine dans un autre écran*:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    START TRANSACTION;
    SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
    UPDATE table2 SET summmary=@A WHERE type=1;
    COMMIT;

    Merci pour cet article,ctxnop.

  8. #8
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Citation Envoyé par aspkiddy Voir le message
    Je pense que j'ai trouvé la solution :
    faire une requête sql avec l’ordre aléatoire via Order by Rand ()
    Donc s'il y a plusieurs consultations de formulaire en même temps par différents utilisateurs, le risque d'avoir plusieurs mêmes codes est très minimum...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string sqlBDD = "SELECT cd_promo FROM client order by rand() LIMIT 1";
    Qu'en vous dites sur cette solution?

    Comme dit plus haut, tu ajoute un champs CDFLAG (ou tu l'appelle comme tu veux), que tu mets à jour dans une transaction et tu retourne le numéro mis à jour après le COMMIT; ainsi tu es sur de l'absence de collision.

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

Discussions similaires

  1. Changement de codes pour plusieurs pages en même temps
    Par d-85a dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 01/05/2013, 23h38
  2. Application accessible par plusieurs utilisateurs en même temps..
    Par flamby6969 dans le forum Modélisation
    Réponses: 3
    Dernier message: 30/03/2009, 00h42
  3. plusieurs utilisateurs en mème temps
    Par Anthony17 dans le forum Access
    Réponses: 3
    Dernier message: 21/06/2006, 15h55
  4. Réponses: 4
    Dernier message: 14/10/2004, 17h36
  5. requête mysql sous php
    Par remi59 dans le forum Débuter
    Réponses: 9
    Dernier message: 03/07/2003, 10h39

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