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

Accès aux données Discussion :

Database et Multithreads


Sujet :

Accès aux données

  1. #21
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par h2s84 Voir le message
    Bah ! Ton code marche ouais et elle ne fait pas une seule ligne de plus parce que tout simplement tu as préféré bénéficier du Dispose de la connexion pour "rollbacker" la transaction et ainsi ne pas avoir à écrire la ligne de plus qui aurait fait la différence dont je te parlais. As-tu pensé aux autres développeurs débutants qui viendront après toi qui se mettront à chercher où se trouve la ligne tran.Rollback(); ? T'imagines les 5 minutes précieuses que tu leur fais perdre. OK je déconne mais ...
    Le code de l'article MSDN aussi profite du rollback implicite lors du dispose.
    J'imagine que TransactionScope aussi a une manière explicite pour rollbacker
    On ne jouit bien que de ce qu’on partage.

  2. #22
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bluedeep Voir le message
    Si, si; d'où mon intervention, visant à "cadrer" le message de BenoitM.
    Je me permet de bumper ce topic, car je suis très impatient d'avoir une réponse sur le comment faire une transaction imbriquée avec C# et Sql Server.

    En effet, d'après mes tests, pas moyen de créer une transaction alors qu'une transaction est déjà existante.

    Pas moyen non plus de spécifiquer s'il s'agit d'une transaction concurrente ou imbriquée (d'un autre côté, vu que je peux pas en créer une seconde, j'imagine que c'est normal que je ne puisse pas dire comment elle doit se comporter )
    On ne jouit bien que de ce qu’on partage.

  3. #23
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 177
    Points : 4 489
    Points
    4 489
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Je me permet de bumper ce topic, car je suis très impatient d'avoir une réponse sur le comment faire une transaction imbriquée avec C# et Sql Server.

    En effet, d'après mes tests, pas moyen de créer une transaction alors qu'une transaction est déjà existante.

    Pas moyen non plus de spécifiquer s'il s'agit d'une transaction concurrente ou imbriquée (d'un autre côté, vu que je peux pas en créer une seconde, j'imagine que c'est normal que je ne puisse pas dire comment elle doit se comporter )
    Il m'aurait cadré à tort?
    Je ne suis qu'un pauvre débutant alors ne frappez pas si mes idées ne sont pas bonnes

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Je me permet de bumper ce topic, car je suis très impatient d'avoir une réponse sur le comment faire une transaction imbriquée avec C# et Sql Server.
    Pour ma part, quand j'ai à le faire (je parle bien en transaction impriquée au sein d'une seule connexion) je le fais via le SQL (rappel : on peut balancer un script complet à un Execute* de ADO.Net en séparant les commandes par des ";"). Faudrait que je retrouve un code d'un ancien projet, mais là je n'en ai pas sous la main. (je pense à un projet en particulier, chez mon précédent client, je dois pouvoir avoir accès aux codes réalisés).

    En effet, d'après mes tests, pas moyen de créer une transaction alors qu'une transaction est déjà existante.
    Sur l'objet Transaction de ADO.Net, c'est possible (je vais vérifier, un peu plus tard).

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  5. #25
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Habituellement, j'ai besoin de transactions imbriquées plutôt en fonction de l'IHM.

    Genre l'utilisateur crée une commande (début de la transaction).
    Il ajoute des produits (transaction imbriquée).
    Il modifie la quantité du produit, et des propriétés (couleur, etc.) dans une transaction imbriquée.
    Et en cas de problème (pas de disponibilité de son produit en rose avec des stickers Hello Kitty par exemple), selon une fenêtre d'invite, il doit pouvoir rollbacker les différents niveaux d'imbrication de transaction : revenir au coloris de base, retirer le produit, ou carrément annuler sa commande.

    Alors avec des Save(), si la cinématique est séquentielle, on s'en sort, mais si par exemple le contrôle de stock se fait une fois l'intégralité de la commande saisie, c'est plus complexe d'aller annuler la ligne 2 sur 4 de la commande si on a utilisé des Save().

    Il faudrait que je regarde si OleDbConnnexion supporte les transactions imbriquées. Puisque le drivers OLEDB pour SQL Server 7 le supportait parfaitement depuis VB Script ! (d'où ma surprise de ne pas retrouver le support avec SqlConnection)
    On ne jouit bien que de ce qu’on partage.

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Il faudrait que je regarde si OleDbConnnexion supporte les transactions imbriquées. Puisque le drivers OLEDB pour SQL Server 7 le supportait parfaitement depuis VB Script ! (d'où ma surprise de ne pas retrouver le support avec SqlConnection)
    Effectivement tu soulèves une question.

    De fait, on peut le gérer via les TransactionScope avec le paramètre TransactionScopeOption.RequiresNew pour forcer l'utilisation d'une portée nouvelle, mais cela implique une deuxième connexion sur la base (sans escalader à DTC dans ce cas).

    Vais essayer de trouver un moment (sauf que j'ai pas de Sql Server là où je suis présentement, le client étant de Delphes )

    Mais je maintiens que tu peux le gérer aisément via des ExecuteNonQuery, à condition de ne pas fermer la connexion entre deux commandes.

    En revanche, effectivement, je ne vois pas trop de syntaxe pour le gérer via l'objet SqlTransaction (à la limite c'est un détail).

    Pseudo code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ExecuteNonQuery "BEGIN TRANSACTION trans_extern"
     
    /* modif data ici */
     
    ExecuteNonQuery "BEGIN TRANSACTION trans_intern"
     
    /* modif data trans interne ici */
     
    ExecuteNonQuery   "ROLLBACK TRANSACTION trans_intern"; /* on laisse tomber modif interne */
     
    /* on commit modif externe */
    ExecuteNonQuery "COMMIT TRANSACTION trans_extern"

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  7. #27
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Tu peux laisser une transaction ouverte avec un ExecuteNonQuery ?

    Décidément, j'ai pas la même vision que Microsoft

    Pour moi il était évident que la transaction ouverte et non committée explicitement dans un ExecuteNonQuery était rollbackée

    Si ton exemple fonctionne, effectivement, c'est un moyen pour pallier à cette limitation du connecteur SQL Server.

    Cela dit, à moins d'encapsuler ça dans des objets bien pensés, c'est hyper crade comme approche, on a vite fait de plus savoir où on en est
    On ne jouit bien que de ce qu’on partage.

  8. #28
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    En tout cas, OleDbConnexion ne prends pas plus en charge les transactions imbriquées/parallèles :/

    Exception quand on ouvre une transaction à l'intérieur d'une première :
    Les transactions parallèles ne sont pas prises en charge par OleDbConnection.
    On ne jouit bien que de ce qu’on partage.

  9. #29
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    J'imagine que TransactionScope aussi a une manière explicite pour rollbacker

    La classe TransactionScope n'a pas de méthode [CODEINLINE]Roolback()[CODEINLINE] l'invalidation d'une transaction est implicite via la méthode Dispose()

  10. #30
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Tu peux laisser une transaction ouverte avec un ExecuteNonQuery ?

    Pour moi il était évident que la transaction ouverte et non committée explicitement dans un ExecuteNonQuery était rollbackée
    C'est la même question que j'allais posée. Bizarre que ce code marche. Va falloir que je fasse une recherche là-dessus.

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Si ton exemple fonctionne, effectivement, c'est un moyen pour pallier à cette limitation du connecteur SQL Server.
    Comme déjà dit, je n'ai pas Sql Server sous la main et pas trop le temps là d'installer un Sql Server Express (mais j'essaierai de le trouver dans la semaine).

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  12. #32
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    J'essaie d'implémenter ta méthode, et le résutlat est TRES mitigé.

    Je ne comprends pas une seconde ce qu'il se passe

    Voici les ExecuteQuery envoyés à la base (1 ligne = 1 ExecuteQuery)
    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
     
    BEGIN TRANSACTION bhri
    insert into test (name) values (@name)
    COMMIT TRANSACTION bhri
     
    BEGIN TRANSACTION yffx
    insert into test (name) values (@name)
    ROLLBACK TRANSACTION yffx
     
    BEGIN TRANSACTION wudt
    insert into test (name) values (@name)
      BEGIN TRANSACTION jdnj
      insert into test (name) values (@name)
      COMMIT TRANSACTION jdnj
    ROLLBACK TRANSACTION wudt
     
    BEGIN TRANSACTION gkeu
    insert into test (name) values (@name)
      BEGIN TRANSACTION guvu
      insert into test (name) values (@name)
      ROLLBACK TRANSACTION guvu
    Ert ça plante sur la dernière ligne : il me dit que la transaction guvu n'existe pas !

    Pour le reste, ça se passe comme prévu :
    La transaction "bhri" a bien été commitée
    La transaction "yffx" a bien été rollbackée
    La transaction "wudt" a bien été rollbackée et a annulé la transaction "jdnj"

    Mais là, étrange, impossible de rollbacker une transaction imbriquée (???)

    Mon code :
    Program.cs
    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
     
    using System;
    using System.Data;
    using System.Data.Sql;
    using System.Data.SqlClient;
    using CustomTransaction;
     
    namespace TestNestedTransaction
    {
        class Program
        {
            static void Main(string[] args)
            {
                /*
                Console.WriteLine("Utilisation de transactions imbriquée (B imbriquée dans A)");
                Console.WriteLine("On utilise une librairie custom qui simule une transaction.");
                */
     
                using (SqlConnection cnx = new SqlConnection("Server=localhost\\SQLEXPRESS;Database=testlock;Trusted_Connection=True;"))
                {
                    cnx.Open();
     
                    Console.WriteLine();
                    /*
                    Console.WriteLine("Cas 1 :");
                    Console.WriteLine("- La transaction A est rollbackée");
                    Console.WriteLine("- La transaction B est committée");
                    Console.WriteLine("On s'attend à ce que tout soit rollbacké");
                    */
     
                    MonObj obj0 = new MonObj(cnx);
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj0.MethodA("Cas -1, transaction A");
                        tranA.Commit();
                    }
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj0.MethodA("Cas 0, transaction A");
                        tranA.Rollback();
                    }
     
                    MonObj obj1 = new MonObj(cnx);
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj1.MethodA("Cas 1, transaction A");
                        using (MyTransaction tranB = new MyTransaction(cnx))
                        {
                            tranB.Begin();
                            obj1.MethodB("Cas 1, transaction B");
                            tranB.Commit();
                        }
                        tranA.Rollback();
                    }
     
                    Console.WriteLine();
                    /*
                    Console.WriteLine("Cas 2 :");
                    Console.WriteLine("- La transaction A est committée");
                    Console.WriteLine("- La transaction B est rollbackée");
                    Console.WriteLine("On s'attend à ce que B soit rollbackée, mais que A soit committée");
                    */
     
                    MonObj obj2 = new MonObj(cnx);
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj2.MethodA("Cas 2, transaction A");
                        using (MyTransaction tranB = new MyTransaction(cnx))
                        {
                            tranB.Begin();
                            obj2.MethodB("Cas 2, transaction B");
                            tranB.Rollback();
                        }
                        tranA.Commit();
                    }
     
                    Console.WriteLine();
                    /*
                    Console.WriteLine("Cas 3 :");
                    Console.WriteLine("- La transaction A est committée");
                    Console.WriteLine("- La transaction B est committée");
                    Console.WriteLine("On s'attend à ce que les deux transactions soient committées");
                    */
     
                    MonObj obj3 = new MonObj(cnx);
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj3.MethodA("Cas 3, transaction A");
                        using (MyTransaction tranB = new MyTransaction(cnx))
                        {
                            tranB.Begin();
                            obj3.MethodB("Cas 3, transaction B");
                            tranB.Commit();
                        }
                        tranA.Commit();
                    }
     
                    Console.WriteLine();
                    /*
                    Console.WriteLine("Cas 4 :");
                    Console.WriteLine("- La transaction A est rollbackée");
                    Console.WriteLine("- La transaction B est rollbackée");
                    Console.WriteLine("On s'attend à ce que les deux transactions soient rollbackées");
                    */
     
                    MonObj obj4 = new MonObj(cnx);
     
                    using (MyTransaction tranA = new MyTransaction(cnx))
                    {
                        tranA.Begin();
                        obj4.MethodA("Cas 4, transaction A");
                        using (MyTransaction tranB = new MyTransaction(cnx))
                        {
                            tranB.Begin();
                            obj4.MethodB("Cas 4, transaction B");
                            tranB.Rollback();
                        }
                        tranA.Rollback();
                    }
     
                    Console.WriteLine();
                    Console.WriteLine("Résultat :");
                    using (SqlCommand cmd = cnx.CreateCommand())
                    {
                        cmd.CommandText = "select id, name from test order by id";
                        SqlDataReader da = cmd.ExecuteReader();
                        while (da.Read())
                        {
                            Console.WriteLine("{0}\t{1}", da.GetInt32(0), da.GetString(1));
                        }
                    }
     
                    cnx.Close();
                }
                Console.WriteLine();
                Console.WriteLine("Fin");
                Console.ReadKey(true);
            }
        }
     
        class MonObj
        {
            SqlConnection _c;
            public MonObj(SqlConnection c)
            {
                _c = c;
            }
     
            public void MethodA(string name)
            {
                using (SqlCommand cmd = _c.CreateCommand())
                {
                    cmd.CommandText = "insert into test (name) values (@name)";
                    cmd.Parameters.Add("name", SqlDbType.VarChar, 50).Value = name;
                    Console.WriteLine(cmd.CommandText);
                    cmd.ExecuteNonQuery();
                }
            }
     
            public void MethodB(string name)
            {
                using (SqlCommand cmd = _c.CreateCommand())
                {
                    cmd.CommandText = "insert into test (name) values (@name)";
                    cmd.Parameters.Add("name", SqlDbType.VarChar, 50).Value = name;
                    Console.WriteLine(cmd.CommandText);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
    Et MagicTransaction.cs :
    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
     
    using System;
    using System.Data;
     
    namespace CustomTransaction
    {
        public static class MyRandom
        {
            private static Random rnd;
     
            static MyRandom()
            {
                rnd = new Random();
            }
     
            public static int Next(int min, int max)
            {
                return rnd.Next(min, max);
            }
        }
     
        /// <summary>
        /// Objet qui permet d'effectuer des transactions imbriquées.
        /// On ne catch absolument aucune erreur volontairement.
        /// Attention, les transactions imbriquées ne sont pas supportées par tous les SGBD !
        /// Aussi, la syntaxe peut éventuellement changer d'un SGBD à l'autre.
        /// </summary>
        public class MyTransaction : IDisposable
        {
            // Private attributes
            IDbConnection Cnx;
            bool IsActive = false;
            string Name = string.Empty;
            const int NAME_LENGTH = 4;
     
            /// <summary>
            /// Créée une transaction liée à la connexion
            /// </summary>
            /// <param name="cnx">Connexion ouverte à la base de données.</param>
            public MyTransaction(IDbConnection cnx)
            {
                // On stock la connexion
                Cnx = cnx;
     
                // On crée un nom aléatoire pour la transaction
                string lettres = "abcdefghijklmnopqrstuvwxyz";
                char[] name = new char[NAME_LENGTH];
                for (int i = 0; i < NAME_LENGTH; i++)
                {
                    name[i] = lettres[MyRandom.Next(0, 26)];
                }
     
                Name = string.Concat(name);
                //Console.WriteLine("Transaction créée : {0}", Name);
            }
     
            /// <summary>
            /// Débute une transaction
            /// </summary>
            public void Begin()
            {
                lock (this)
                {
                    using (IDbCommand cmd = Cnx.CreateCommand())
                    {
                        cmd.CommandText = string.Format("BEGIN TRANSACTION {0}", Name);
                        Console.WriteLine(cmd.CommandText);
                        cmd.ExecuteNonQuery();
                    }
                    IsActive = true;
                }
            }
     
            /// <summary>
            /// Valide la transaction
            /// </summary>
            public void Commit()
            {
                lock (this)
                {
                    if (IsActive)
                    {
                        using (IDbCommand cmd = Cnx.CreateCommand())
                        {
                            cmd.CommandText = string.Format("COMMIT TRANSACTION {0}", Name);
                            Console.WriteLine(cmd.CommandText);
                            cmd.ExecuteNonQuery();
                        }
                        IsActive = false;
                    }
                }
            }
     
            /// <summary>
            /// Annule la transaction
            /// </summary>
            public void Rollback()
            {
                lock (this)
                {
                    if (IsActive)
                    {
                        using (IDbCommand cmd = Cnx.CreateCommand())
                        {
                            cmd.CommandText = string.Format("ROLLBACK TRANSACTION {0}", Name);
                            Console.WriteLine(cmd.CommandText);
                            cmd.ExecuteNonQuery();
                        }
                        IsActive = false;
                    }
                }
            }
     
            /// <summary>
            /// Libère les ressources.
            /// Rollback la transaction si elle est encore active.
            /// </summary>
            public void Dispose()
            {
                //Console.WriteLine("Dispose {0}", Name);
                // Le test pour savoir si la transaction est active est déjà pris en compte dans la méthode Rollback()
                Rollback();
            }
        }
    }
    On ne jouit bien que de ce qu’on partage.

  13. #33
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bluedeep Voir le message
    Comme déjà dit, je n'ai pas Sql Server sous la main et pas trop le temps là d'installer un Sql Server Express (mais j'essaierai de le trouver dans la semaine).
    Au pire, Oracle et Access supportent aussi les transactions imbriquées (pour Access, j'ai un très léger doute, mais il me semble bien).
    On ne jouit bien que de ce qu’on partage.

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Au pire, Oracle et Access supportent aussi les transactions imbriquées (pour Access, j'ai un très léger doute, mais il me semble bien).
    Oracle, j'ai
    Pour Access, je n'en sais rieen (et n'ai pas envie de savoir )

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  15. #35
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Oui mais créer un fichier MDB avec l'explorateur Windows, c'est plus facile que d'installer un serveur Oracle, donc pour faire des tests, c'est toujours une solution de repli, même si c'est tout pourri
    On ne jouit bien que de ce qu’on partage.

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Bon, j'ai pris 10 mn pour installer Sql Express

    Et je confirme mes dires :

    le DDL de deux tables de test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    CREATE TABLE [dbo].[Table_2](
    	[t2_id] [int] IDENTITY(1,1) NOT NULL,
    	[t2_text] [nvarchar](50) NULL
    ) ON [PRIMARY]
     
    CREATE TABLE [dbo].[Table_1](
    	[t1_id] [int] IDENTITY(1,1) NOT NULL,
    	[t1_text] [nvarchar](50) NULL
    ) ON [PRIMARY]
    Le code (fait à l'arrache, hein) :

    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
    			SqlConnection connection = new SqlConnection("Data Source=localHost;Initial Catalog=TEST;Integrated Security=true");
     
    			connection.Open();
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "begin transaction trans_1;";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "insert into Table_1 values('test 111');";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "begin transaction trans_2;";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "save transaction trans_2;";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "insert into Table_2 values('test222');";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "rollback transaction trans_2;";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "commit transaction trans_1;";
    				command.ExecuteNonQuery();
    			}
    			using (SqlCommand command = connection.CreateCommand())
    			{
    				command.CommandText = "commit;";
    				command.ExecuteNonQuery();
    			}
     
    			connection.Close();
    A la fin, la ligne de Table_1 est bien insérée, mais celle de Table_2 est "rollbackée".

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  17. #37
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    Pourquoi fais-tu un SAVE de ta transaction 2 avant de t'en servir ?
    On ne jouit bien que de ce qu’on partage.

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

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Citation Envoyé par StringBuilder Voir le message
    Pourquoi fais-tu un SAVE de ta transaction 2 avant de t'en servir ?
    Si ma mémoire est bonne on ne peut pas faire un rollback sur une transaction imbriquée (donc celle qui n'est pas la plus extérieure) sans sauvegarder le point de synchro.
    Le rollback doit s'effectuer normalement sur la plus externe, donc le save permet de ramener cela "au premier plan".

    Voir les détails dans la doc, car ça fait un moment que j'ai pas pratiqué Sql Server, et je cite de mémoire un truc pas utilisé très souvent.

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  19. #39
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    En tout cas, avec le SAVE, ça débloque mon problème.
    (Faudra m'expliquer pourquoi mais bon ^^)

    Par contre, j'en ai un autre... Qui semble venir de SAVE

    Honnêtement, je ne comprends absolument pas ce qu'il se passe dans la tête de SQL Server !

    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
     
    BEGIN TRANSACTION [lzsy]
    SAVE TRANSACTION [lzsy]
    insert into test (name) values ('Cas 1, transaction seule');
    COMMIT TRANSACTION [lzsy]
     
    BEGIN TRANSACTION [zpnn]
    SAVE TRANSACTION [zpnn]
    insert into test (name) values ('Cas 2, transaction seule');
    ROLLBACK TRANSACTION [zpnn]
     
    BEGIN TRANSACTION [jbjx]
    SAVE TRANSACTION [jbjx]
    insert into test (name) values ('Cas 3, transaction parente');
      BEGIN TRANSACTION [sdot]
      SAVE TRANSACTION [sdot]
      insert into test (name) values ('Cas 3, transaction fille');
      COMMIT TRANSACTION [sdot]
    ROLLBACK TRANSACTION [jbjx]
     
    BEGIN TRANSACTION [emed]
    SAVE TRANSACTION [emed]
    insert into test (name) values ('Cas 4, transaction parente');
      BEGIN TRANSACTION [nsze]
      SAVE TRANSACTION [nsze]
      insert into test (name) values ('Cas 4, transaction fille');
      ROLLBACK TRANSACTION [nsze]
    COMMIT TRANSACTION [emed]
     
    BEGIN TRANSACTION [glye]
    SAVE TRANSACTION [glye]
    insert into test (name) values ('Cas 5, transaction parente');
      BEGIN TRANSACTION [givs]
      SAVE TRANSACTION [givs]
      insert into test (name) values ('Cas 5, transaction fille');
      COMMIT TRANSACTION [givs]
    COMMIT TRANSACTION [glye]
     
    BEGIN TRANSACTION [zolw]
    SAVE TRANSACTION [zolw]
    insert into test (name) values ('Cas 6, transaction parente');
      BEGIN TRANSACTION [kkub]
      SAVE TRANSACTION [kkub]
      insert into test (name) values ('Cas 6, transaction fille');
      ROLLBACK TRANSACTION [kkub]
    ROLLBACK TRANSACTION [zolw]
    => C'est ce que je joue dans mon programme de test.

    Et je me rends compte que seule la transaction 1 ([lzsy]) est bien terminée.
    En effet, si je lis la table par la suite, seule la ligne de la transaction 1 est bien sauvegardée !

    Et quand je lance depuis Entreprise Manager, il me dit que des transactions ne sont pas terminées.

    J'imagine que les SAVE sont responsable. Pourtant, si je ne les met pas, il ne veut pas rollbacker une transaction fille.

    Bref, c'est quoi le binz ?
    On ne jouit bien que de ce qu’on partage.

  20. #40
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 147
    Points : 7 392
    Points
    7 392
    Billets dans le blog
    1
    Par défaut
    J'ai essayé de virer le "SAVE" quand j'étais au premier niveau (comme dans l'exemple de Bluedeep), et je retrouve mon problème initial lors du rollback de la transaction fille du cas 6... (alors que les 5 autres cas sont passés, notamment le 4 qui est strictement identique au 6 par rapport à là où ça plante)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    begin
      insert
      begin
      save
        insert
      rollback
    => Le 4 et le 6 ont se bout de code, strictement identique (c'est la ligne suivante qui plante).
    Pourtant, le 4 passe, et pas le 6.

    Je sens que je vais péter un plomb

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    BEGIN TRANSACTION [lwvh]
      insert into test (name) values ('Cas 4, transaction parente');
      BEGIN TRANSACTION [ghpo]
      SAVE TRANSACTION [ghpo]
        insert into test (name) values ('Cas 4, transaction fille');
      ROLLBACK TRANSACTION [ghpo]
    COMMIT TRANSACTION [lwvh]
     
    BEGIN TRANSACTION [vais]
      insert into test (name) values ('Cas 6, transaction parente');
      BEGIN TRANSACTION [dxjx]
      SAVE TRANSACTION [dxjx]
        insert into test (name) values ('Cas 6, transaction fille');
      ROLLBACK TRANSACTION [dxjx]

    C'est quoi la différence ?
    (on ne parle pas du commit final du cas 4, puisqu'on plante sur le rollback...)
    On ne jouit bien que de ce qu’on partage.

Discussions similaires

  1. Redhat-9 changer le path des databases
    Par jean christophe dans le forum Installation
    Réponses: 7
    Dernier message: 30/05/2003, 17h53
  2. [BDE] Ou peut-on telecharger le Borland Database Engine?
    Par Robert A. dans le forum Autres SGBD
    Réponses: 2
    Dernier message: 27/05/2003, 10h01
  3. Blob (interbase) d'une Database à l'autre
    Par TOM-Z dans le forum XMLRAD
    Réponses: 2
    Dernier message: 18/05/2003, 21h57
  4. Multithreading sous HP Ux 11
    Par pykoon dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 18/10/2002, 23h36
  5. Tutoriels et liens pour le Borland Database Engine
    Par Community Management dans le forum Paradox
    Réponses: 0
    Dernier message: 25/03/2002, 10h23

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