# Wednesday, February 27, 2008

[LINQ] Importer du CSV en deux lignes de code

Plus j'écris du code reposant sur le framework 3.5 et plus je me rends compte que j'écris de moins en moins de boucles. Ce n'est peut-être pas toujours l'idéal en terme de performances, mais je dois avouer que si je peux écrire une requête LINQ au lieu d'écrire une boucle, je penche plutôt pour la première solution tant je trouve l'écriture de requêtes simples et "belles".

Un exemple tout bête pour faire un import CSV. Je suis en train de travailler sur un logiciel de gestion de finance perso (nommé iThunes :)) et afin d'importer mes opérations bancaires, ma banque me propose un fichier au format CSV dont le séparateur est la virgule. Il ressemble à peu près à ça :

image

Afin de manipuler les opérations au sein de mon application, j'ai donc créé une entité toute simple :

namespace iThunes.Entities
{
    public class Operation
    {
        public DateTime DateOperation
        { get; set; }

        public DateTime Valeur
        { get; set; }

        public decimal Debit
        { get; set; }

        public decimal Credit
        { get; set; }

        public string Libelle
        { get; set; }

        public decimal Solde
        { get; set; }
    }
}

Et finalement l'import d'un fichier CSV afin de récupérer une List<Operation> se fait de manière très simple grâce à LINQ :

namespace iThunes.Importers
{
    public class CSVImporter
    {
        public static List&lt;Entities.Operation&gt; LoadFile(string filename)
        {
            CultureInfo inv=CultureInfo.InvariantCulture;

            var operations = from line in System.IO.File.ReadAllLines(filename)
                         let fields = line.Split(new char[] { ',' })
                         select new Entities.Operation
                         { 
                             DateOperation = DateTime.Parse(fields[0]), 
                             Valeur = DateTime.Parse(fields[1]), 
                             Debit=fields[2].Length&gt;0? decimal.Parse(fields[2],inv):0 ,
                             Credit=fields[3].Length&gt;0?decimal.Parse(fields[3],inv):0,
                             Libelle = fields[4],
                             Solde=decimal.Parse(fields[5],inv)
                         };

           return operations.ToList();
        }
    }
}

Pas besoin d'écrire un boucle afin de parcourir le fichier ligne par ligne et pour ensuite découper la ligne en champs grâce au séparateur et instancier une Operation correspondante. Une simple requête LINQ et c'est bouclé.