none
AccessViolationException avec Sql Sever Ce RRS feed

  • Discussion générale

  • Bonjour,

    Je rencontre un problème, une erreur AccessViolationException qui se produit dans des circonstances bien précises.

    Alors, le problème se présente lors de l'insertion de données en base de données SQL Server Ce. Ceci avec une application codée en C#.

    A l'initialisation de notre application, de nombreuses données sont insérées en base dans une transaction, en l'occurrence 131952 lignes de données dans différentes tables. Tout se passe bien pour toutes les données, sauf qu'approximativement toujours au même moment (jamais exactement sur le même id de ligne mais toujours sur la même table que l'on va appeller T), l'application s'arrête à cause d'un AccessViolationException. Dans la table T, nous tentons d'inserer envirion 6000 lignes.

    Losque que je relance l'application en ne faisant pas les insertions dans la table T, tout se passe bien. Soit plus de 125000 insertions qui se passent sans problème.

    Lorsque je relance l'application en n'effectuant que les insertions dans la table T, l'erreur se produit à nouveau.

    En effectuant des recherches par tatonnement, il s'avère que ce qui pose problème est un ligne contenant un texte de 4500 caractères (sans caractères spéciaux). Cette ligne n'est pas la dernière insérée, l'erreur se produit quelques centaines d'insertions après cette ligne.

    Pourtant, le champ destiné à recevoir cette ligne est bien un NText dans la table (et de toute façon, l'insertion marche).

    Si, on coupe cette ligne pour qu'elle n'en fasse plus que 4100 caractères, tout se passe à nouveau bien et aucune erreur n'est provoquée.

    Il semblerait que le framework ou sql server ce ne gère pas bien cette longueur (pourtant, la ligne entière ne dépasse pas 8Ko) et provoque une incohérence en mémoire qui se répercute quelques dizaines/centaines d'insertions plus tard.

    Après recherche, j'ai trouvé ce billet qui semble parler d'un problème similaire, mais cela ne concerne que de machines 64 bits (http://support.microsoft.com/kb/970269), or le problème se produit sur des machines 32 bits et 64 bits de la même façon. De plus, l'application de ce patch sur ma machine 64 bits n'a rien changé.

    Est-ce que quelqu'un aurait eu connaissance de ce problème ? Y'a t'il des informations dessus ? Est-ce possible de savoir quel est l'enchaînement d'actions qui provoque cette erreur sachant que le code marche très bien dans d'autres cas ?

    Merci d'avance pour l'aide apportée.

    Cordialement.

    mardi 1 juin 2010 08:09

Toutes les réponses

  • Bonjour,

     

    Quelles versions de SQL Server et .NET Framework utilisez-vous ? Est-il possible d’écrire ici la procédure d’insertion des données dans la base ?

     

    Cordialement,

    Alex

    __________________________________________________________________________________________

    Publiez un article sur une de ces technologies : Visual Basic, C#, C++, .NET, ASP.NET, SQL Server, Silverlight, SharePoint 2010, SharePoint 2007

     

    Astuces pour Visual Studio 2010

    Didacticiels et astuces : VB.NET, C#, ASP.NET, .NET Framework, Workflow Foundation

     

     

    mardi 1 juin 2010 15:05
  • Bonjour,

    On utilise le framework .NET 3.5 et Sql Server Ce 3.5 SP1.

    Les données sont contenues dans un flux xml, chaque noeud de ce flux est une entrée dans une des tables de la base. Le flux est donc découpé, chaque noeud est transformé en une requête qui est insérée.

    Le tout est effectué dans une seule transaction.

    La string incriminée ne contient pas de caractère mal encodés, spéciaux ou autre, cela a été testé.

    Les insertions sont séquentielles même si le programme est multi-theadé, à ce moment là, aucun autre thread n'accède à la base. De toute façon, les accès à la base sont lockés de façon à ce que cela n'entre pas en jeu.

    La chose la plus étrange, c'est que l'on a effectué un test. Nous avons récupéré la déclaration de la table incriminée, recrée cette table dans une petite base de test et inséré en boucle dans une même transaction des milliers de lignes contenant la string incriminée et cela a été impossible de reproduire ce bug. Tout s'est bien passé.

    Il doit y avoir quelque chose qui met le framework ou sql server ce dans un état qui provoque un décalage dans la mémoire ou quelque chose du genre, mais quoi ?

    Y'a t'il quelque chose de connu dans ce style ?

    Merci d'avance.

    Cordialement.

    mercredi 2 juin 2010 07:18
  • Bonjour,

    Pouvez-vous m'envoyer un projet qui reproduirait le problème sur gilles.tourreau@pos.fr ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCP - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mercredi 2 juin 2010 09:38
    Modérateur
  • Bonjour,

    C'est très gentil à vous de proposer cela, malheureusement non, je ne peux pas vous délivrer de code qui reproduit le problème.

    Je ne peux pas vous délivrer l'application complète et on n'a pas réussi à reproduire le problème avec un projet de test (je peux vous le délivrer celui-là, mais ça ne vous aidera pas beaucoup, je pense)

    Même avec la chaine incriminée, l'erreur ne se reproduit pas.

    L'erreur ne se produit que dans le projet complet, lorsqu'il y a cette chaine de 4500 caractères. Nous avons réduit cette chaîne à 4100 et tout se passe bien.

    Connaissez-vous des cas particuliers où cette erreur se produit ?
    Peut-être y a-t'il une information que je ne communique pas parce qu'elle ne semble pas liée alors qu'en fait, cela pourrait être l'origine ?

    Cordialement.

    vendredi 4 juin 2010 07:56
  • Bonjour,

    pourrais tu donner la trace de l'exception remontée ?

    Cordialement

    vendredi 4 juin 2010 09:32
  • Bonjour,

    Oui, elle est quelque peu laconique mais là voilà :


    "[xSynchro] - System.Exception: Unable to rollback transaction SynchroDescendante ---> System.AccessViolationException: Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.
    à System.Data.SqlServerCe.NativeMethods.AbortTransaction(IntPtr pTx, IntPtr pError)
    à System.Data.SqlServerCe.SqlCeTransaction.Rollback()
    à x.x.DataBase.Transaction.RollBack(Boolean A_0)
    --- Fin de la trace de la pile d'exception interne ---
    à x.x.DataBase.Transaction.Rollback(Boolean A_0)
    à x.x.DataBase.Transaction.Dispose()
    à x.x.Synchronisation.Descendante.SynchronisationDescendante.Receive(IServeur A_0, j A_1, p A_2, ad A_3, BytesDownload A_4, r A_5, IUser A_6)
    à x.x.Synchronisation.Gestion.GestionSynchro.DoSynchro(Object A_0)
    "

    Cordialement.

    lundi 7 juin 2010 16:08
  • Bonjour,

    Il semblerait que cela soit un bogue de SQL Server CE. Sans un protocole de reproduction il est très difficile de remonter l'information à Microsoft... :'-(

    Cordialement


    Gilles TOURREAU - MVP C# - MCP - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 8 juin 2010 18:04
    Modérateur

  • Bonjour,

    C'est un peu la conclusion à laquelle on était arrivé, malheureusement.
    Pour le moment, on est peut être sur une piste, on a peut être identifier quelque chose. Je reviendrai poster quand j'en saurai plus.

    Merci pour vos interventions.

    (il semblerait que la chaîne de caractères trop longue soit coupée et que, même si la chaîne est correcte au départ, une fois inséré, elle serait tronquée avec ajout de caractères disons étranges de ce style ?+5 à vérifier).

    Cordialement.

    mercredi 9 juin 2010 15:29
  • Bonjour,

    Bon, alors, il s'avère que j'ai réussi à récupérer une base avec l'erreur dedans, mais je ne l'explique toujours pas. Je n'ai pas pu le faire en debug, je l'ai juste reproduit sur mon poste, en local ce qui a eu pour effet de faire planter le logiciel

    J'ai donc inséré hors transaction une chaine de caractère longue de plus de 4000 caractères dans le champ considéré.

    Pour insérer les données dans la table, on effectue les insertions de la façon suivante :  

     using (IDbCommandEx cmd = connection.CreateCommand(query))
    {
                
    // 4 ème paramètre
    param = cmd.CreateParameter();
    param.DbType = System.Data.DbType.String;
    param.Size = Int32.MaxValue;
    param.ParameterName = "@AddressTo";
    cmd.Parameters.Add(param);
    ...
    val = this.AddressTo;
    if (val == null)
    {
      cmd.Parameters[3].Value = DBNull.Value;
    }
    else
    {
      cmd.Parameters[3].Value = val;
    }
    ...
    cmd.ExecuteNonQuery();
    
    

    Pour le coup, dans le logiciel, il y a eu un gros crash, avec une belle erreur AccesViolationMemory : System.AccessViolationException: Tentative de lecture ou d'écriture de mémoire protégée. Cela indique souvent qu'une autre mémoire est endommagée.

    Bref, cependant, j'ai récupéré la base, et il s'avère que la chaîne est tronquée après 4005 caractères. Juste après ces 4005 caractères, il y a un lot de caractères bizarres puis plus rien, la chaîne est tronquée. Je pense que c'est le même phénomère qui se produit lors de l'insertion massive dont je parlais plus haut.

    Et chose toujours étrange, c'est que lorsque je fais un petit projet avec la même façon de se connecter, d'insérer, etc... impossible de reproduire le bug. L'insertion se passe sans soucis.

    Est-ce que quelqu'une aurait entendu parler d'un truc comme ça ? Une coupure qui provoque des erreur après 4005 caractères ?

    (je précise, le champ considéré dans la base est bien un NText).

    Merci d'avance.

    Cordialement.

    mercredi 16 juin 2010 09:27
  • Bonjour,

    Essayez de changer :

    param.DbType = System.Data.DbType.String;
    

    en

    param.SqlDbType = SqlDbType.NText;

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    jeudi 24 juin 2010 19:47
    Modérateur
  • Bonjour,

    (ça fait un bout de temps mais je n'ai pas oublié).

    Merci pour votre réponse.

    Je vais essayer ça et je reviens poster dès que j'en sais plus.

    Cordialement.

    mardi 17 août 2010 14:48
  • Bonjour,

     

    Pour conclure, je n'ai, malheureusement trouvé aucune réponse, ni réelle explication.

    Comme sql server ce limite la taille de chaque ligne dans la base 8K, on a limité la taille des chaînes de caractères et si on a besoin de plus, on crée des sous-tables et on effectue des jointures...

    Le problème de ne produit plus depuis cette modification. Cela n'apporte pas d'explication, je le sais.

     

    Cordialement.

    lundi 12 septembre 2011 08:09
  • Bonjour,

    Avez-vous essayé de changer le type de paramètre comme je l'ai proposé dans le dernier post ?

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte .NET/Consultant/Formateur chez Winwise
    Blog : http://gilles.tourreau.fr
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5
    lundi 12 septembre 2011 08:27
    Modérateur