Lors de la lecture d'un fichier CSV à l'aide d'un DataReader et du fournisseur de données OLEDB Jet, comment puis-je contrôler les types de données de colonne?

StackOverflow https://stackoverflow.com/questions/115658

  •  02-07-2019
  •  | 
  •  

Question

Dans mon application C #, j'utilise le fournisseur de données OLEDB Microsoft Jet pour lire un fichier CSV. La chaîne de connexion ressemble à ceci:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Data;Extended Properties="text;HDR=Yes;FMT=Delimited

J'ouvre une connexion ADO.NET OleDbConnection à l'aide de cette chaîne de connexion et sélectionne toutes les lignes du fichier CSV à l'aide de la commande:

select * from Data.csv

Lorsque j'ouvre un OleDbDataReader et examine les types de données des colonnes renvoyées, un élément de la pile a tenté de deviner les types de données en fonction de la première ligne de données du fichier. Par exemple, supposons que le fichier CSV contienne:

House,Street,Town
123,Fake Street,Springfield
12a,Evergreen Terrace,Springfield

L'appel de la méthode OleDbDataReader.GetDataTypeName pour la colonne Maison indique que la colonne a reçu le type de données "DBTYPE_I4", de sorte que toutes les valeurs qui y sont lues sont interprétées comme des entiers. Mon problème est que House doit être une chaîne. Lorsque je tente de lire la valeur de House à partir de la deuxième ligne, OleDbDataReader renvoie la valeur null.

Comment puis-je demander au fournisseur de base de données Jet ou à OleDbDataReader d'interpréter une colonne sous forme de chaînes au lieu de nombres?

Était-ce utile?

La solution

Vous pouvez créer un fichier de schéma indiquant à ADO.NET comment interpréter le fichier CSV - en lui donnant une structure.

Essayez ceci: http://www.aspdotnetcodes.com/Importing_CSV_Database_Schema.ini.xx. a>

Autres conseils

Veuillez vérifier

http://kbcsv.codeplex.com/

using (var reader = new CsvReader("data.csv"))
{
    reader.ReadHeaderRecord();
    foreach (var record in reader.DataRecords)
    {
        var name = record["Name"];
        var age = record["Age"];
    }
}

Vous devez indiquer au pilote d'analyser toutes les lignes pour déterminer le schéma. Sinon, si les premières lignes sont numériques et les autres alphanumériques, les cellules alphanumériques sont vides.

Comme Rory , j'ai constaté que je devais créer un fichier schema.ini de manière dynamique car il n'y avait aucun moyen de le programmer. Indiquez au pilote d'analyser toutes les lignes. (ce n'est pas le cas pour les fichiers Excel)

Vous devez avoir MaxScanRows = 0 dans votre schema.ini

.

Voici un exemple de code:

    public static DataTable GetDataFromCsvFile(string filePath, bool isFirstRowHeader = true)
    {
        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException("The path: " + filePath + " doesn't exist!");
        }

        if (!(Path.GetExtension(filePath) ?? string.Empty).ToUpper().Equals(".CSV"))
        {
            throw new ArgumentException("Only CSV files are supported");
        }
        var pathOnly = Path.GetDirectoryName(filePath);
        var filename = Path.GetFileName(filePath);
        var schemaIni =
            <*>quot;[{filename}]{Environment.NewLine}" +
            <*>quot;Format=CSVDelimited{Environment.NewLine}" +
            <*>quot;ColNameHeader={(isFirstRowHeader ? "True" : "False")}{Environment.NewLine}" +
            <*>quot;MaxScanRows=0{Environment.NewLine}" +
            <*>quot; ; scan all rows for data type{Environment.NewLine}" +
            <*>quot; ; This file was automatically generated";
        var schemaFile = pathOnly != null ? Path.Combine(pathOnly, "schema.ini") : "schema.ini";
        File.WriteAllText(schemaFile, schemaIni);

        try
        {
            var sqlCommand = $@"SELECT * FROM [{filename}]";

            var oleDbConnString =
                <*>quot;Provider=Microsoft.Jet.OLEDB.4.0;Data Source={pathOnly};Extended Properties=\"Text;HDR={(isFirstRowHeader ? "Yes" : "No")}\"";

            using (var oleDbConnection = new OleDbConnection(oleDbConnString))
            using (var adapter = new OleDbDataAdapter(sqlCommand, oleDbConnection))
            using (var dataTable = new DataTable())
            {
                adapter.FillSchema(dataTable, SchemaType.Source);
                adapter.Fill(dataTable);
                return dataTable;
            }
        }
        finally
        {
            if (File.Exists(schemaFile))
            {
                File.Delete(schemaFile);
            }
        }
    }

Vous aurez besoin de faire quelques modifications si vous exécutez ceci sur le même répertoire dans plusieurs threads en même temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top