C# 使用混合数据类型从CSV文件读取数据

C# 使用混合数据类型从CSV文件读取数据,c#,asp.net,sql,C#,Asp.net,Sql,只要每个“项目”都是数字或每个项目都是字母数字,这项功能就可以工作。当我有数字和字母数字的“项”时,它不能正确填充值 代码如下: public void updateInventory() { try { if (File.Exists(inventoryUpdateDirectory + "inventoryUpdate.csv")) { csvReader csv = new csvReader();

只要每个“项目”都是数字或每个项目都是字母数字,这项功能就可以工作。当我有数字和字母数字的“项”时,它不能正确填充值

代码如下:

public void updateInventory()
{
    try
    {
        if (File.Exists(inventoryUpdateDirectory + "inventoryUpdate.csv"))
        {
            csvReader csv = new csvReader();
            DataTable inventory = csv.read(inventoryUpdateDirectory + "inventoryUpdate.csv");
            //int test = inventory.Rows.Count;
            string sql = "";

            foreach (DataRow inventoryItem in inventory.Rows)
            {
                try
                {
                    sql = " Update Inventory set OnHand = " + inventoryItem[1] + " WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'";
                    //executeSQL(sql);
                }
                catch { }
            }

            File.Delete(inventoryUpdateDirectory + "inventoryUpdate.csv");
        }
        else
        {
            writeToFile("fileDoesntExist", inventoryUpdateDirectory + "error.txt");
        }
    }
    catch { }
}
下面是它读取的文件:

ALB001,0
ALB002,66
10001,0
10016,348
这将有助于:

ALB001,0
ALB002,66
10001,0
10016,348
这将有助于:

ALB001,0
ALB002,66
10001,0
10016,348
这是行不通的:

ALB001,0
ALB002,66
10001,0
10016,348
它将
inventoryItem
数组填充为空
{}

+       inventoryItem[0]    {}  object {System.DBNull}
其值应为
ALB001

CSV中的第一个“列”应始终视为字符串,因为它可以包含字母数,第二个“列”始终为数字

有人能帮我弄清楚吗

我想我只需要编辑sql查询,将它们转换为字符串,但我不确定

CSV阅读器编辑:

namespace CSV
{
    public class csvReader
    {
        public DataTable read(string strFileName)
        {
            OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = \"Text;HDR=NO;FMT=Delimited\"");
            conn.Open();
            string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
            OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn);
            DataSet ds = new DataSet("CSV File");
            adapter.Fill(ds);
            return ds.Tables[0];
        }

        public DataTable read(string strFileName, bool firstRowHeaders)
        {
            string hdr = "NO";
            if (firstRowHeaders) { hdr = "YES"; }

            OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " + System.IO.Path.GetDirectoryName(strFileName) + "; Extended Properties = \"Text;HDR=" + hdr + ";FMT=Delimited\"");
            conn.Open();
            string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
            OleDbDataAdapter adapter = new OleDbDataAdapter(strQuery, conn);
            DataSet ds = new DataSet("CSV File");
            adapter.Fill(ds);
            return ds.Tables[0];
        }
    }
}

在下面的示例中,我在现有值周围添加了单引号,以告诉SQL它应该始终使用字符串。您最好将SQL语句更改为使用“@Parameters”并内联赋值

sql = " Update Inventory set OnHand = '" + inventoryItem[1] + "' WHERE Sku = '" + inventoryItem[0].ToString().Trim() + "'";

问题显然出在CsvReader类中。因为你没有附上它的源代码,所以很难知道为什么它没有用内容填充数据表,我能做的就是猜测

我将尝试通过建议您使用codeproject中的csv阅读器来帮助您:

您不需要使用数据表,因为它使您能够使用简单的while循环对文件行进行迭代。您的代码如下所示:

using (CsvReader reader = new CsvReader(FilePath, Encoding.Default))
{
   while (reader.ReadNextRecord())
   {
          sql = " Update Inventory set OnHand = " + reader.Fields[1] + " WHERE Sku = '" + reader.Fields[0] + "'";
   }
} 

您可以使用LINQ读取CSV

var data = (from line in File.ReadAllLines(fileName).AsParallel()
            select line.Split(',')).ToList();

然后进行适当的铸造、更新。

我知道这是一个较老的问题,我已经尝试了许多方法来解决类似的问题,所以我想我会提供我的解决方案。即使我使用的是C#,您也可以继承VB库,TextFieldParser库可以很好地处理这一点。对于我的数据,我不知道将导入多少列,尽管每行的列数相同。某些列包含逗号,但未被引号“”包围。我首先创建了一个DataTable,将所有列转换为字符串,稍后将在其中验证类型。我还删除了文件的头行,我首先使用它创建DataTable。我希望这能帮助别人

我正在使用的数据示例:

校长1,校长2,校长3
A,123,A
B,123,A
C,A,一些数据,然后 更多数据

这是我最终提出的解决方案,效果很好

using Microsoft.VisualBasic.FileIO;

        private static DataTable GetDataTableFromCsv(string path)
        {
            var dataTable = new DataTable("ImportData");
            var rows = File.ReadAllLines(path);
            var columns = rows[0].Split(',');
            foreach (var column in columns)
            {
                dataTable.Columns.Add(new DataColumn(column.Trim(), typeof(string)));
            }
            using (var parser = new TextFieldParser(path))
            {
                parser.Delimiters = new[] { "," };
                while (true)
                {
                    var parts = parser.ReadFields();
                    dataTable.Rows.Add(parts);
                    if (parser.EndOfData) break;
                }
            }
            dataTable.Rows[0].Delete();
            return dataTable;
        }

不要使用内联SQL,使用参数并定义您的数据类型。这是由另一位不再在这里的开发人员完成的,目前不允许重写。什么是csvReader?几乎可以肯定问题是从这里开始的。它失败了,因为它看到的第一个值“OnHand”将由它看到的第一个值字符串暗示,但几行之后您将其更改为int。最好是用“”包装该值,告诉SQL它总是得到一个隐藏SQL注入文件的字符串。如果不能完全控制输入,请始终使用参数。空的catch块比没有try/catch更糟糕。这并没有解决它。不管怎么说,手头的总是一个数字。Sku(具有单个刻度)可以是数字或字母数字。我希望这可以解决它,但和以前一样=(好吧,根据你发布的代码,你对如何生成CSV没有太多控制权。我强烈建议用我在回答中建议的CsvReader替换CsvReader。它可靠、非常快速,最重要的是,它让你完全控制如何读取CSV文件。我强烈建议你像其他人一样,不要使用显式SQL查询,但要使用参数。您的应用程序高度暴露于SQL注入。我完全同意您的看法,如果我可以重新编写此内容,我会(我使用的所有内容都有using语句、参数等)。我只需要听上面的人说。我将查看您发布的示例,看看是否可以快速完成此操作。:)我下载了这个,并把它扔进了现有的项目中,使用了上面的例子,效果非常好。非常感谢。这是否需要我花费大量时间重新编写现有代码来处理这个新对象?我只是在寻找最简单的解决方案,使现有的代码基础工作。我仍然是asp.net的不速之客,这让我在重写现有内容时不寒而栗。使用逗号拆分不符合csv规范。例如,如果第一列的值本身包含逗号,那么它将生成包含3列而不是2列的结果。但是,通过调用“安全拆分”行而不是行的方法,它可以很容易地转换为csv投诉代码。拆分调用我可以看到,这将花费您几分钟的时间,因为您有一个列表来填充您的数据表。而且它会更干净。@KobyMizrahy我认为读取结构良好的CSV数据没有问题。您还可以将“跳过”(1)添加到跳过列标题。ReadAllLines返回一个字符串数组。每个字符串包含文件的一行。ReadAllText返回一个包含文件所有行的字符串,结果字符串不包含终止回车符和/或换行符。@plurby-我想强调的是,使用逗号分割csv数据不符合csv规范。例如,如果要保存值“我是一个包含逗号的字符串”,则将使用双引号保存该值。csv阅读器应该显式处理这种情况,否则会导致上面的字符串被拆分为两个不同的列,这是不需要的。帮助我。谢谢