简体   繁体   English

使用schema.ini的C#import CSV文件创建表但不加载数据

[英]C# import CSV file with schema.ini creates table but doesn't load data

I need to import some CSV files into a temporary table inside an MDB database. 我需要将一些CSV文件导入MDB数据库中的临时表。 The files come from a file upload on an ASP.NET Web application. 这些文件来自ASP.NET Web应用程序上的文件上载。

This is my CSV file: 这是我的CSV文件:

"Operating Unit Organization Name";"Year";"Sales Rep Name";"Date";"Week";"Product Number";"Account Name";"Customer Number";"Corporate Brand";"Brand";"Ordered Quantity";"Amount"
"IT Operating Unit";2014;"Name-561004";2014-02-21;"2014 Week08";"123456+";"Buyer name";"456789";"Corp Brand";"Brand";4;147,52
"IT Operating Unit";2014;"Name-561004";2014-02-21;"2014 Week08";"123.012EXP";"Buyer name";"789123";"Corp Brand";"Brand";10;204,9
"IT Operating Unit";2014;"Name-561004";2014-02-17;"2014 Week08";"101S-3";"Buyer name";"234567";"Another Corp Brand";"Another Brand";30;237,5

This is the method that generates the schema.ini file. 这是生成 schema.ini文件的方法。 Since it has to contain the name of the CSV file, I generate a new schema file each time I upload a new CSV, because I need to save them all on a folder with specific name. 由于它必须包含CSV文件的名称,因此每次上传新CSV时都会生成新的模式文件,因为我需要将它们全部保存在具有特定名称的文件夹中。

private void CreateCsvSchemaFile()
    {
        using (FileStream fs = new FileStream(Path.GetDirectoryName(FilePath) + "\\schema.ini", FileMode.Create, FileAccess.Write))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.WriteLine("[" + Path.GetFileName(FilePath) + "]");
                sw.WriteLine("ColNameHeader=True");
                //sw.WriteLine("MaxScanRows=0");
                sw.WriteLine("Format=Delimited(;)");
                sw.WriteLine("DateTimeFormat=yyyy-MM-dd");
                sw.WriteLine("CharacterSet=ANSI");
                sw.WriteLine("DecimalSymbol=,");
                sw.WriteLine("Col1=\"Operating Unit Organization Name\" Text Width 255");
                sw.WriteLine("Col2=\"Year\" Long");
                sw.WriteLine("Col3=\"Sales Rep Name\" Text Width 255");
                sw.WriteLine("Col4=\"Date\" DateTime");
                sw.WriteLine("Col5=\"Week\" Text Width 255");
                sw.WriteLine("Col6=\"Product Number\" Text Width 255");
                sw.WriteLine("Col7=\"Account Name\" Text Width 255");
                sw.WriteLine("Col8=\"Customer Number\" Text Width 255");
                sw.WriteLine("Col9=\"Corporate Brand\" Text Width 255");
                sw.WriteLine("Col10=\"Brand\" Text Width 255");
                sw.WriteLine("Col11=\"Ordered Quantity\" Long");
                sw.WriteLine("Col12=\"Amount\" Currency");
                sw.Close();
                sw.Dispose();
            }

            fs.Close();
            fs.Dispose();
        }
    }

The schema.ini file is always generated correctly and in fact the table on the db is created with the correct field names and types. schema.ini文件始终正确生成,实际上db上的表是使用正确的字段名称和类型创建的。

This is the method that execute the CSV import . 这是执行CSV导入的方法。

private void ImportCsvIntoTemp()
    {
        try
        {
            CreateCsvSchemaFile();

            string query = @"SELECT * INTO TEMP_CSV 
                                FROM [Text;HDR=no;Database={0}].[{1}]";

            query = String.Format(query, Path.GetDirectoryName(FilePath), Path.GetFileName(FilePath));

            AccessDb.Query(AccessDbConnString, query);
        }
        catch (Exception ex)
        {
            string message = String.Format("CSV file import failed. Inner Exception: {0}", ex.Message);
            throw new ImportFailedException(message);
        }
    }

The table TEMP_CSV is created correctly but no data is loaded into it . TEMP_CSV已正确创建, 但未加载任何数据 Instead, if I open the MDB with Access I see 8 empty rows. 相反,如果我用Access打开MDB,我会看到8个空行。 I tried to change some parameters on the schema.ini file such as add/remove MaxScnaRows=0 , CharacterSet , and so on... and on the query I also tried to change the FROM Properties , but I always get the same result. 我试图更改schema.ini文件中的一些参数,例如添加/删除MaxScnaRows=0CharacterSet等等......在查询中我也尝试更改FROM Properties ,但我总是得到相同的结果。

-- EDIT Added AccessDb.Query() method and the database connection string -- - 编辑添加了AccessDb.Query()方法和数据库连接字符串 -

I didn't include the Query() method because AccessDb it's just a "DB tier" class that contains methods that create connection to db and execute query/list query/scalar with/without parameters. 我没有包含Query()方法,因为AccessDb只是一个“DB层”类,它包含创建与db的连接并执行带/不带参数的查询/列表查询/标量的方法。 I'm using this class in other pages and also in many other applications. 我在其他页面以及许多其他应用程序中使用此类。

Anyway, this is the AccessDb.Query() method. 无论如何,这是AccessDb.Query()方法。

public static void Query(string connString, string query)
    {
        OleDbConnection conn = new OleDbConnection(connString);

        try
        {
            conn.Open();
            OleDbCommand cmd = conn.CreateCommand();
            cmd.CommandText = query;
            cmd.ExecuteNonQuery();
            cmd.Dispose();
        }
        catch (OleDbException odbEx)
        {
            throw odbEx;
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            conn.Dispose();
            conn.Close();
        }
    }

This is my database connection string, configured inside Web.config file. 这是我的数据库连接字符串,在Web.config文件中配置。

<connectionStrings>
    <add name="DefaultConnection" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Progetti\Personale\Progetti\Infomed\Database\Infomed.mdb;User Id=admin;Password=;" />
</connectionStrings>

The code that you posted is essentially correct. 您发布的代码基本上是正确的。 I copied and pasted it into a new C# project and tweaked it just enough to get it to run. 我将其复制并粘贴到一个新的C#项目中,并将其调整到足以让它运行。 When I did get it to run it worked fine, creating the new table and importing all three (3) rows into it. 当我确实让它运行时,它工作正常,创建新表并将所有三(3)行导入其中。

The main difference is that I just used the following code to execute the SELECT * INTO ... query. 主要区别在于我只是使用以下代码来执行SELECT * INTO ...查询。 Instead of... 代替...

AccessDb.Query(AccessDbConnString, query);

...I used... ...我用了...

using (OleDbConnection con = new OleDbConnection())
{
    con.ConnectionString =
            @"Provider=Microsoft.Jet.OLEDB.4.0;" +
            @"Data Source=C:\Users\Public\test\CsvImportTest\MyDb.mdb;";
    con.Open();
    using (OleDbCommand cmd = new OleDbCommand())
    {
        cmd.Connection = con;
        cmd.CommandText = query;
        cmd.ExecuteNonQuery();
    }
    con.Close();
}

The complete code is: 完整的代码是:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Data.OleDb;

namespace CsvImportTest
{
    class Program
    {
        static string FilePath = @"C:\Users\Public\test\CsvImportTest\TestData.csv";

        static void Main(string[] args)
        {
            ImportCsvIntoTemp();
            Console.WriteLine("Done.");
        }

        private static void ImportCsvIntoTemp()
        {
            try
            {
                CreateCsvSchemaFile();

                string query = @"SELECT * INTO TEMP_CSV 
                                FROM [Text;HDR=no;Database={0}].[{1}]";

                query = String.Format(query, Path.GetDirectoryName(FilePath), Path.GetFileName(FilePath));

                //AccessDb.Query(AccessDbConnString, query);
                using (OleDbConnection con = new OleDbConnection())
                {
                    con.ConnectionString =
                            @"Provider=Microsoft.Jet.OLEDB.4.0;" +
                            @"Data Source=C:\Users\Public\test\CsvImportTest\MyDb.mdb;";
                    con.Open();
                    using (OleDbCommand cmd = new OleDbCommand())
                    {
                        cmd.Connection = con;
                        cmd.CommandText = query;
                        cmd.ExecuteNonQuery();
                    }
                    con.Close();
                }
            }
            catch (Exception ex)
            {
                string message = String.Format("CSV file import failed. Inner Exception: {0}", ex.Message);
                Console.WriteLine(message);
                //throw new ImportFailedException(message);
            }
        }

        private static void CreateCsvSchemaFile()
        {
            using (FileStream fs = new FileStream(Path.GetDirectoryName(FilePath) + "\\schema.ini", FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.WriteLine("[" + Path.GetFileName(FilePath) + "]");
                    sw.WriteLine("ColNameHeader=True");
                    //sw.WriteLine("MaxScanRows=0");
                    sw.WriteLine("Format=Delimited(;)");
                    sw.WriteLine("DateTimeFormat=yyyy-MM-dd");
                    sw.WriteLine("CharacterSet=ANSI");
                    sw.WriteLine("DecimalSymbol=,");
                    sw.WriteLine("Col1=\"Operating Unit Organization Name\" Text Width 255");
                    sw.WriteLine("Col2=\"Year\" Long");
                    sw.WriteLine("Col3=\"Sales Rep Name\" Text Width 255");
                    sw.WriteLine("Col4=\"Date\" DateTime");
                    sw.WriteLine("Col5=\"Week\" Text Width 255");
                    sw.WriteLine("Col6=\"Product Number\" Text Width 255");
                    sw.WriteLine("Col7=\"Account Name\" Text Width 255");
                    sw.WriteLine("Col8=\"Customer Number\" Text Width 255");
                    sw.WriteLine("Col9=\"Corporate Brand\" Text Width 255");
                    sw.WriteLine("Col10=\"Brand\" Text Width 255");
                    sw.WriteLine("Col11=\"Ordered Quantity\" Long");
                    sw.WriteLine("Col12=\"Amount\" Currency");
                    sw.Close();
                    sw.Dispose();
                }

                fs.Close();
                fs.Dispose();
            }
        }


    }
}

Check the code you are using to actually execute the SELECT * INTO ... query and see if you can find a significant difference between your code and mine. 检查您用来实际执行SELECT * INTO ...查询的代码,看看您是否能找到代码和我的代码之间的重大差异。

Finally I found where the problem was. 最后我找到了问题所在。 First you should pay attention to the Character set of the file you want to import. 首先,您应该注意要导入的文件的字符集。 You've to be sure that is ANSI if you set the schema.ini file to ANSI. 如果将schema.ini文件设置为ANSI,则必须确保是ANSI。 Then I also had some troubles with the "DecimalSymbol=," option. 然后我也遇到了一些"DecimalSymbol=,"选项的麻烦。 After removing it the import worked fine. 删除后导入工作正常。 Anyway, with my locale setting (Italia (Italiano)) it should be correct, since the decimal symbol is ',' ... 无论如何,使用我的语言环境设置(Italia(Italiano))它应该是正确的,因为小数符号是',' ...

So this is the final method that creates the schema.ini file. 所以这是创建schema.ini文件的最终方法。

private void CreateCsvSchemaFile()
    {
        using (FileStream fs = new FileStream(Path.GetDirectoryName(FilePath) + "\\schema.ini", FileMode.Create, FileAccess.Write))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.WriteLine("[" + Path.GetFileName(FilePath) + "]");
                sw.WriteLine("ColNameHeader=True");
                sw.WriteLine("Format=Delimited(;)");
                sw.WriteLine("DateTimeFormat=yyyy-MM-dd");
                sw.WriteLine("CharacterSet=ANSI");
                sw.WriteLine("Col1=\"Operating Unit Organization Name\" Text Width 255");
                sw.WriteLine("Col2=\"Year\" Long");
                sw.WriteLine("Col3=\"Sales Rep Name\" Text Width 255");
                sw.WriteLine("Col4=\"Date\" DateTime");
                sw.WriteLine("Col5=\"Week\" Text Width 255");
                sw.WriteLine("Col6=\"Product Number\" Text Width 255");
                sw.WriteLine("Col7=\"Account Name\" Text Width 255");
                sw.WriteLine("Col8=\"Customer Number\" Text Width 255");
                sw.WriteLine("Col9=\"Corporate Brand\" Text Width 255");
                sw.WriteLine("Col10=\"Brand\" Text Width 255");
                sw.WriteLine("Col11=\"Ordered Quantity\" Long");
                sw.WriteLine("Col12=\"Amount\" Currency");
                sw.Close();
                sw.Dispose();
            }

            fs.Close();
            fs.Dispose();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM