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

 .NET Discussion :

Insert CSV dans BDD (champs qui se déplacent)


Sujet :

.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 111
    Par défaut Insert CSV dans BDD (champs qui se déplacent)
    Bonjour à tous,

    J'ai une petite question pour l'insert de données csv dans une table :

    On m'envoie des fichiers csv avec une première ligne d’entête, seulement mon client change l'ordre des colonnes systématiquement (chaque semaine).

    J'aimerai faire quelque chose d'un peu plus dynamique qui puisse me permettre de ne pas réécrire mes requêtes à chaque fois que l'ordre des
    colonnes change.

    Ci joint tout mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //Je récupère le contenu du CSV et je le lis dans un reader
    while (!reader.EndOfStream)
    {
    var line = reader.ReadLine();
    var data = line.Split(';');
     
    _maDal.ConsoliderDonnees(data);
    }
    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
    // La méthode qui INSERT OR UPDATE les données dans ma BDD
    public void ConsoliderDonnees(string[] data)
            {
                    using (DbCommand cmd = GetProcedureStockeeCommande("dbo.INSERT_OR_UPDATE_DONNEES"))
                    {
                        cmd.CommandTimeout = TimeOut;
     
                        for (int i = 0; i < data.Length; i++)
                        {
                            AddInParameter(cmd, string.Concat("data", i), data[i]);
                        }
                        ExecuteNonQuery(cmd);
                    }
                });
            }
    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
    //Ma ProcStoc
    CREATE PROCEDURE [dbo].[INSERT_OR_UPDATE_DONNEES] 
    (
    @data0 BIGINT, 
    @data1 NVARCHAR(50), 
    @data2 MONEY, 
    @data3 NVARCHAR(50), 
    @data4 INT
    )
    AS 
      BEGIN 
     
        SET nocount ON; 
     
    	IF NOT EXISTS(SELECT * FROM donnee where donnee_id=@data0)
     
    	INSERT INTO donnee (donnee_id,donnee_ref,donnee_prix,donnee_variable,Actif)
        VALUES (@data0,@data1,@data2,@data3,@data4)
     
    	ELSE
     
    	UPDATE donnee SET donnee_ref=@data1, donnee_prix=@data2, donnee_variable= @data3, Actif = @data4
    	WHERE donnee_id=@data0
     
    	END

    Je veux donc juste récupérer la place du champs dans l’entête et mettre la valeur au bon endroit car dès fois @data3 est à la place de @data4. Existe-il un moyen de faire cela ?

    Merci beaucoup d'avance

  2. #2
    Membre éclairé
    Avatar de Etanne
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2003
    Messages
    469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 469
    Par défaut
    Bonjour,

    Vous pouvez convertir les données du CSV en objet !

    Voici une solution que j'ai développé. Cela vous permettra de ne plus vous soucier de l'ordre des colonnes

    Vous pouvez faire une classe comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        public class SchoolPlayer
        {
            [CsvColumn(Name = "playerID")]
            public string Id { get; set; }
     
            [CsvColumn(Name = "schoolID")]
            public string SchoolId { get; set; }
        }
    Comme vous pouvez le voir chaque propriété de mon objet possède un attribut avec une valeur, cette valeur représente le nom de la colonne dans le fichier CSV.


    Ensuite pour "parser" mon fichier je fais cela (en indiquant un nom de fichier) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Je créé mon converteur
    using(var converter = new CsvConverter<SchoolPlayer>(filePath, ',', true))
    {
        // Je boucle sur chaque ligne
        foreach (SchoolPlayer schoolPlayer in converter.Read())
        {
            // Maintenant j'ai une ligne de mon fichier CSV sous forme objet ! \o/
            Debug.WriteLine("ID du joueur : {0}, ID de l'école : {1}", schoolPlayer.Id, schoolPlayer.SchoolId);
        }
    }
    Ou via un tableau de strings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // Extraction des données
    string[] lignes = File.ReadAllLines(filePath);
    // Je créé mon converteur
     
    using (var converter = new CsvConverter<SchoolPlayer>(lignes, ',', true))
    {
        // Je boucle sur chaque ligne
        foreach (SchoolPlayer schoolPlayer in converter.Read())
        {
            // Maintenant j'ai une ligne de mon fichier CSV sous forme objet ! \o/
            Debug.WriteLine("ID du joueur : {0}, ID de l'école : {1}", schoolPlayer.Id, schoolPlayer.SchoolId);
        }
    }
    Le convertisseur :
    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
    /// <summary>
        /// Convertisseur CSV en objet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class CsvConverter<T> : IDisposable where T : new()
        {
            private readonly string _filePath;
            private readonly char _separator;
            private readonly bool _hasDoubleQuote;
            private string[] _headers;
            private readonly DatasType _datasType;
            private readonly string[] _arrayDatas;
     
            private enum DatasType
            {
                Filename,
                StringArray
            }
     
            private StreamReader _reader;
     
            /// <summary>
            /// 
            /// </summary>
            /// <param name="filePath">Chemin vers le fichier CSV</param>
            /// <param name="separator">Séparateur de colonne</param>
            /// <param name="hasDoubleQuote">true si " est utilisé entre les valeurs</param>
            public CsvConverter(string filePath, char separator, bool hasDoubleQuote)
            {
                _datasType = DatasType.Filename;
                _filePath = filePath;
                _separator = separator;
                _hasDoubleQuote = hasDoubleQuote;
            }
     
            public CsvConverter(string[] readLines, char separator, bool hasDoubleQuote)
            {
                _datasType = DatasType.StringArray;
                _arrayDatas = readLines;
                _separator = separator;
                _hasDoubleQuote = hasDoubleQuote;
            }
     
            /// <summary>
            /// Lire les données
            /// </summary>
            /// <returns>Retourne l'objet </returns>
            public IEnumerable<object> Read()
            {
                if (_datasType == DatasType.Filename)
                    foreach (var obj in ReadByFileName())
                        yield return obj;
                else
                {
                    foreach (var obj in ReadByArrayDatas())
                        yield return obj;
                }
            }
     
            /// <summary>
            /// Lire les données dans le cas où on a donné un nom de fichier
            /// </summary>
            /// <returns></returns>
            private IEnumerable<object> ReadByFileName()
            {
                if (ExtractHeader())
                {
                    while (_reader.Peek() >= 0)
                    {
                        yield return ConvertToObject(_reader.ReadLine());
                    }
                }
                _reader.Dispose();
            }
     
            /// <summary>
            /// Lire les données dans le cas où l'on a donné un tableau de données
            /// </summary>
            /// <returns></returns>
            private IEnumerable<object> ReadByArrayDatas()
            {
                if (ExtractHeader())
                {
                    foreach (var data in _arrayDatas.Skip(1))
                    {
                        yield return ConvertToObject(data);
                    }
                }
            }
     
            /// <summary>
            /// Convertir une ligne en objet
            /// </summary>
            /// <param name="line"></param>
            /// <returns></returns>
            private T ConvertToObject(string line)
            {
                // Extraction des valeurs
                var values = ExtractValues(line);
     
                var obj = new T();
                // Pour chaque colonne
                for (var i = 0; i < _headers.Length && i < values.Length; i++)
                {
                    foreach (var propertyInfo in typeof(T).GetProperties())
                    {
                        if (propertyInfo.GetCustomAttributes(typeof(CsvColumnAttribute), true).Count(attr => ((CsvColumnAttribute)attr).Name == _headers[i]) == 0)
                            continue;
     
                        propertyInfo.SetValue(obj, values[i]); // on affecte la valeur
                    }
                }
     
                return obj;
            }
     
     
            /// <summary>
            /// Extraire l'en-tête
            /// </summary>
            /// <returns>Retourne false si vide</returns>
            private bool ExtractHeader()
            {
                var line = string.Empty;
                if (_datasType == DatasType.Filename)
                {
                    _reader = new StreamReader(_filePath);
                    line = _reader.ReadLine();
                }
                else if (_arrayDatas.Length > 0)
                {
                    line = _arrayDatas[0];
                }
     
                if (string.IsNullOrEmpty(line))
                {
                    return false;
                }
     
                _headers = ExtractValues(line);//line.Split(new[] {_separator});
     
                return true;
            }
     
            /// <summary>
            /// Extraire les valeurs d'une ligne
            /// </summary>
            /// <param name="line">Ligne</param>
            /// <returns>Tableau de valeurs</returns>
            private string[] ExtractValues(string line)
            {
                var values = line.Split(new[] { _separator });
     
                if (!_hasDoubleQuote) return values;
     
                var list = values.Select(value => value.Replace("\"", string.Empty)).ToList();
     
                return list.ToArray();
            }
     
            public object GetObject()
            {
                throw new NotImplementedException();
            }
     
            public void Dispose()
            {
                if (_reader != null)
                _reader.Dispose();
            }
    Et...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public class CsvColumnAttribute : Attribute
        {
            public string Name { get; set; }
        }
    L'outil devrait être fonctionnel

    Etanne

  3. #3
    Membre éclairé Avatar de k4st0r42
    Homme Profil pro
    Artisan numérique
    Inscrit en
    Janvier 2012
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Artisan numérique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 48
    Par défaut
    Etanne, Sympathique ton bout de code =)

Discussions similaires

  1. insert into dans BDD a partir d un fichier csv
    Par btsgreta77 dans le forum JDBC
    Réponses: 3
    Dernier message: 22/04/2009, 15h18
  2. Insert into dans un champ de type "timestamp"
    Par sylvette dans le forum Langage SQL
    Réponses: 2
    Dernier message: 30/10/2007, 17h35
  3. Réponses: 1
    Dernier message: 23/07/2007, 20h57
  4. [MySQL] importer des données .csv dans BDD MySql
    Par priscillia dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 15/06/2007, 09h40
  5. INSERT INTO dans un champ mémo
    Par Cri Cross dans le forum VBA Access
    Réponses: 12
    Dernier message: 05/03/2007, 16h24

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