【问题标题】:C# import CSV file with schema.ini creates table but doesn't load dataC# 使用 schema.ini 导入 CSV 文件创建表但不加载数据
【发布时间】:2014-03-05 10:16:20
【问题描述】:

我需要将一些 CSV 文件导入到 MDB 数据库中的临时表中。 这些文件来自 ASP.NET Web 应用程序上的文件上传。

这是我的 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

这是生成schema.ini 文件的方法。由于它必须包含 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();
        }
    }

schema.ini 文件始终正确生成,实际上数据库上的表是使用正确的字段名称和类型创建的。

这是执行 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);
        }
    }

TEMP_CSV 已正确创建但未加载任何数据。 相反,如果我使用 Access 打开 MDB,我会看到 8 个空行。我尝试更改schema.ini 文件上的一些参数,例如添加/删除MaxScnaRows=0CharacterSet 等等...在查询中我也尝试更改FROM Properties,但我总是得到同样的结果。

-- EDIT 添加了AccessDb.Query() 方法 和数据库连接字符串--

我没有包含Query() 方法,因为AccessDb 它只是一个“数据库层”类,其中包含创建与数据库的连接并执行带/不带参数的查询/列表查询/标量的方法。我在其他页面和许多其他应用程序中使用这个类。

不管怎样,这是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();
        }
    }

这是我的数据库连接字符串,在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>

【问题讨论】:

  • 您添加的代码很有帮助,但我们仍然不知道您的connString 是什么样的。
  • 添加了连接字符串!

标签: c# sql ms-access csv jet


【解决方案1】:

您发布的代码基本上是正确的。我将它复制并粘贴到一个新的 C# 项目中,并对其进行了调整以使其运行。当我让它运行时,它运行良好,创建新表并将所有三 (3) 行导入其中。

主要区别在于我只是使用下面的代码来执行SELECT * INTO ... 查询。而不是...

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();
}

完整代码为:

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();
            }
        }


    }
}

检查您用于实际执行SELECT * INTO ... 查询的代码,看看您是否能发现您的代码与我的代码之间存在显着差异。

【讨论】:

  • 感谢测试!至少我知道它有效......不知何故!我在原始帖子中添加了AccessDb.Query() 方法定义。看看...
  • @RainbowCoder 好吧,我注意到的一件事是您的代码使用了OleDbCommand 对象,而我的使用了OdbcCommand 对象。 MSDN 页面“Schema.ini File (Text File Driver)”绝对是 MSDN 库的 ODBC 部分的一部分。
  • 好的...但是,由于 OLEDB 是 Microsoft 围绕 ODBC 的“包装器”,这是一个较旧的 API,为什么它不起作用?另见:link
  • OLEDB 应该比 ODBC 更有效。无论如何,我无法重构我的 AccessDb 类,因为我还使用它来访问非关系数据库,例如 .XLS 和 .XML 文件。您可以尝试使用 Oledb 驱动程序和我到 .MDB 文件的连接字符串吗?
  • @RainbowCoder 可能有所作为的一件事是 Windows 区域设置。我的是“英语(美国)”。如果您的设置有所不同,那么您可以尝试在 Windows 的区域设置控制面板中暂时将其设置为“英语(美国)”,看看是否有任何不同。 (它不应该,但是....)
【解决方案2】:

我终于找到了问题所在。 首先要注意要导入的文件的字符集。如果您将schema.ini 文件设置为ANSI,您必须确保它是ANSI。 然后我在"DecimalSymbol=," 选项上也遇到了一些麻烦。删除它后,导入工作正常。无论如何,使用我的语言环境设置(Italia (Italiano))应该是正确的,因为十进制符号是 ','...

所以这是创建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();
        }
    }

【讨论】:

    猜你喜欢
    • 2014-02-23
    • 2013-10-27
    • 2020-08-25
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多