当我使用C#将csv文件放入Sql Server时,某些字段写入错误?

当我使用C#将csv文件放入Sql Server时,某些字段写入错误?,c#,sql-server,csv,C#,Sql Server,Csv,您好,我在将csv文件导入sql server时遇到问题,此csv文件包含需要保存在sql server数据库中的文章。导入(使用下面编写的代码c#完成)完成后,作为导入的某些字段(descripione和CodArt)在数据库中写入不正确,并且具有奇怪的字符。下载csv文件 SqlServer在蓝线上的导入不正确: 导入C#代码: using (var rd = new StreamReader(labelPercorso.Text)) { Articolo a = new Arti

您好,我在将csv文件导入sql server时遇到问题,此csv文件包含需要保存在sql server数据库中的文章。导入(使用下面编写的代码c#完成)完成后,作为导入的某些字段(descripione和CodArt)在数据库中写入不正确,并且具有奇怪的字符。下载csv文件

SqlServer在蓝线上的导入不正确:

导入C#代码:

using (var rd = new StreamReader(labelPercorso.Text))
{
    Articolo a = new Articolo();
    a.db = this.db;

    while (!rd.EndOfStream)
    {
        //setto codean e immagine =null ad ogni giro 
        CodEAN = "";
        Immagine = "";

        try
        {
            var splits = rd.ReadLine().Split(';');
            CodArt = splits[0];
            Descrizione = splits[1];
            String Price = splits[2];
            Prezzo = decimal.Parse(Price);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Non è presente nè immagine nè codean");
        }

        a.Prezzo = Prezzo;
        a.CodiceArticolo = CodArt;
        a.Descrizione = Descrizione;
        a.Fornitore = fornitore;
        //manca da controllare se l'articolo è presente e nel caso aggiornalo
        a.InserisciArticoloCSV();
    }
}
功能代码:InserisciArticoloCSV

try
{
    SqlConnection conn = db.apriconnessione();
    String query = "INSERT INTO Articolo(CodArt,Descrizione,Prezzo,PrezzoListino,Fornitore,Importato,TipoArticolo) VALUES(@CodArt,@Descrizione,@Prezzo,@PrezzoListino,@Fornitore,@Importato,@TipoArticolo)";
    String Importato = "CSV";
    String TipoArticolo = "A";
    SqlCommand cmd = new SqlCommand(query, conn);
   // MessageBox.Show("CodArt: " + CodiceArticolo + "\n Descrizione :" + Descrizione + "\n Prezzo: " + Prezzo);  
    cmd.Parameters.AddWithValue("@CodArt", CodiceArticolo.ToString());
    cmd.Parameters.AddWithValue("@Descrizione", Descrizione.ToString());
    cmd.Parameters.AddWithValue("@Prezzo", Prezzo);
    cmd.Parameters.AddWithValue("@PrezzoListino", Prezzo);
    cmd.Parameters.AddWithValue("@Fornitore", Fornitore.ToString());
    cmd.Parameters.AddWithValue("@Importato", Importato.ToString());
    cmd.Parameters.AddWithValue("@TipoArticolo", TipoArticolo.ToString());
    cmd.ExecuteNonQuery();

    db.chiudiconnessione();               
    conn.Close();

    return true;

}
catch (Exception ex)
{
    Console.WriteLine("Errore nell'inserimento dell'articolo " + ex);
    //MessageBox.Show("Errore nel inserimento dell'articolo:  " + ex);
    return false;
}

您的CSV文件格式不好,中间有中间的回车符,这会破坏解析。在Notepad++中查看该文件并打开换行符,这就是您所发现的


因此,对于格式为的行,数据导入工作正常,而对于其他行,逻辑不工作。

您的CSV文件格式不正确,中间有中间回车,这会导致解析出错。在Notepad++中查看该文件并打开换行符,这就是您所发现的


因此,对于格式为的行,数据导入工作正常,对于其他行,逻辑不工作。

读取文件时,应指定正确的编码。是utf吗?它是带有特定代码页的ascii码吗?您还应该指定Sql参数的SqlDbType,特别是字符串参数,它们将是varchar或nvarchar,它们之间有很大的区别

// what is the encoding of your file? This is an example using code page windows-1252
var encoding = Encoding.GetEncoding("windows-1252");
using (var file = File.Open(labelPercorso.Text, FileMode.Open))
using (var reader = new StreamReader(file, encoding))
{
  // rest of code unchanged
}
Sql代码。注意,我为实现
IDisposable
的类型添加了
,比如连接和命令

try
{
    String query = "INSERT INTO Articolo(CodArt,Descrizione,Prezzo,PrezzoListino,Fornitore,Importato,TipoArticolo) VALUES(@CodArt,@Descrizione,@Prezzo,@PrezzoListino,@Fornitore,@Importato,@TipoArticolo)";
    String Importato = "CSV";
    String TipoArticolo = "A";

    using(SqlConnection conn = db.apriconnessione())
    using(SqlCommand cmd = new SqlCommand(query, conn))
    {
        // -1 indicates you used MAX like nvarchar(max), otherwise use the maximum number of characters in the schema
        cmd.Parameters.Add(new SqlDbParameter("@CodArt", SqlDbType.NVarChar, -1)).Value = CodiceArticolo.ToString();
        cmd.Parameters.Add(new SqlDbParameter("@Descrizione", SqlDbType.NVarChar, -1)).Value = Descrizione.ToString();

        /*
          Rest of your parameters created in the same manner
        */

        cmd.ExecuteNonQuery();
        db.chiudiconnessione();               
    }
    return true;
}
catch (Exception ex)
{
    Console.WriteLine("Errore nell'inserimento dell'articolo " + ex);
    //MessageBox.Show("Errore nel inserimento dell'articolo:  " + ex);
    return false;
}

读取文件时,应指定正确的编码。是utf吗?它是带有特定代码页的ascii码吗?您还应该指定Sql参数的SqlDbType,特别是字符串参数,它们将是varchar或nvarchar,它们之间有很大的区别

// what is the encoding of your file? This is an example using code page windows-1252
var encoding = Encoding.GetEncoding("windows-1252");
using (var file = File.Open(labelPercorso.Text, FileMode.Open))
using (var reader = new StreamReader(file, encoding))
{
  // rest of code unchanged
}
Sql代码。注意,我为实现
IDisposable
的类型添加了
,比如连接和命令

try
{
    String query = "INSERT INTO Articolo(CodArt,Descrizione,Prezzo,PrezzoListino,Fornitore,Importato,TipoArticolo) VALUES(@CodArt,@Descrizione,@Prezzo,@PrezzoListino,@Fornitore,@Importato,@TipoArticolo)";
    String Importato = "CSV";
    String TipoArticolo = "A";

    using(SqlConnection conn = db.apriconnessione())
    using(SqlCommand cmd = new SqlCommand(query, conn))
    {
        // -1 indicates you used MAX like nvarchar(max), otherwise use the maximum number of characters in the schema
        cmd.Parameters.Add(new SqlDbParameter("@CodArt", SqlDbType.NVarChar, -1)).Value = CodiceArticolo.ToString();
        cmd.Parameters.Add(new SqlDbParameter("@Descrizione", SqlDbType.NVarChar, -1)).Value = Descrizione.ToString();

        /*
          Rest of your parameters created in the same manner
        */

        cmd.ExecuteNonQuery();
        db.chiudiconnessione();               
    }
    return true;
}
catch (Exception ex)
{
    Console.WriteLine("Errore nell'inserimento dell'articolo " + ex);
    //MessageBox.Show("Errore nel inserimento dell'articolo:  " + ex);
    return false;
}

正如其他人指出的,您有许多问题,编码、回车和大量空白。此外,在数据库中使用单个插入,速度非常慢。我在下面展示了一些示例代码,它演示了如何处理所有这些问题

IFormatProvider fP = new CultureInfo("it");
DataTable tmp = new DataTable();
tmp.Columns.Add("CodArt", typeof(string));
tmp.Columns.Add("Descrizione", typeof(string));
tmp.Columns.Add("Prezzo", typeof(decimal));
using (var rd = new StreamReader("yourFileName", Encoding.GetEncoding("iso-8859-1")))
{
    while (!rd.EndOfStream)
    {
        try
        {
            var nextLine = Regex.Replace(rd.ReadLine(), @"\s+", " ");
            while (nextLine.Split(';').Length < 3)
            {
                nextLine = nextLine.Replace("\r\n", "") + Regex.Replace(rd.ReadLine(), @"\s+", " ");
            }
            var splits = nextLine.Split(';');
            DataRow dR = tmp.NewRow();
            dR[0] = splits[0];
            dR[1] = splits[1];
            string Price = splits[2];
            dR[2] = decimal.Parse(Price, fP);
            tmp.Rows.Add(dR);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

using (var conn = db.apriconnessione())
{
    var sBC = new SqlBulkCopy(conn);
    conn.Open();
    sBC.DestinationTableName = "yourTableName";
    sBC.WriteToServer(tmp);
    conn.Close();
}
ifformatprovider fP=新文化信息(“it”);
DataTable tmp=新DataTable();
tmp.Columns.Add(“CodArt”,typeof(string));
tmp.Columns.Add(“descripione”,typeof(string));
tmp.Columns.Add(“Prezzo”,typeof(decimal));
使用(var rd=newstreamreader(“yourFileName”,Encoding.GetEncoding(“iso-8859-1”))
{
而(!rd.EndOfStream)
{
尝试
{
var nextLine=Regex.Replace(rd.ReadLine(),@“\s+”,”);
while(nextLine.Split(“;”)。长度<3)
{
nextLine=nextLine.Replace(“\r\n”,”)+Regex.Replace(rd.ReadLine(),@“\s+”,”);
}
var splits=nextLine.Split(“;”);
DataRow dR=tmp.NewRow();
dR[0]=拆分[0];
dR[1]=拆分[1];
字符串价格=拆分[2];
dR[2]=decimal.Parse(价格,fP);
tmp.Rows.Add(dR);
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
}
}
使用(var conn=db.apriconnessione())
{
var sBC=新的SqlBulkCopy(conn);
conn.Open();
sBC.DestinationTableName=“yourTableName”;
sBC.WriteToServer(tmp);
康涅狄格州关闭();
}
现在需要一些解释:

首先,我将解析后的值存储在数据表中。请注意,我只包含CSV中的三个字段。实际上,您必须提供其他列,并用每行的正确值填充额外的列。我只是懒惰,但我相信你会明白的

我不知道您的csv文件是什么编码,但是
iso-8859-1
对我来说很有用

我使用正则表达式将多个空格替换为单个空格

如果任何行没有所需的拆分数,我会继续添加更多行(删除回车符),直到我点击成功

一旦我有了一个完整的行,我现在可以拆分它,并将它分配给新的DataRow(请参阅我上面的注释以获得额外的列)

最后,一旦文件被读取,DataTable将拥有所有的行,并且可以使用BulkCopy上传到数据库。这太快了


PS你的一些行有双引号。你可能也想把这些也扔掉

正如其他人指出的,您有许多问题,编码、回车和大量空白。此外,在数据库中使用单个插入,速度非常慢。我在下面展示了一些示例代码,它演示了如何处理所有这些问题

IFormatProvider fP = new CultureInfo("it");
DataTable tmp = new DataTable();
tmp.Columns.Add("CodArt", typeof(string));
tmp.Columns.Add("Descrizione", typeof(string));
tmp.Columns.Add("Prezzo", typeof(decimal));
using (var rd = new StreamReader("yourFileName", Encoding.GetEncoding("iso-8859-1")))
{
    while (!rd.EndOfStream)
    {
        try
        {
            var nextLine = Regex.Replace(rd.ReadLine(), @"\s+", " ");
            while (nextLine.Split(';').Length < 3)
            {
                nextLine = nextLine.Replace("\r\n", "") + Regex.Replace(rd.ReadLine(), @"\s+", " ");
            }
            var splits = nextLine.Split(';');
            DataRow dR = tmp.NewRow();
            dR[0] = splits[0];
            dR[1] = splits[1];
            string Price = splits[2];
            dR[2] = decimal.Parse(Price, fP);
            tmp.Rows.Add(dR);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

using (var conn = db.apriconnessione())
{
    var sBC = new SqlBulkCopy(conn);
    conn.Open();
    sBC.DestinationTableName = "yourTableName";
    sBC.WriteToServer(tmp);
    conn.Close();
}
ifformatprovider fP=新文化信息(“it”);
DataTable tmp=新DataTable();
tmp.Columns.Add(“CodArt”,typeof(string));
tmp.Columns.Add(“descripione”,typeof(string));
tmp.Columns.Add(“Prezzo”,typeof(decimal));
使用(var rd=newstreamreader(“yourFileName”,Encoding.GetEncoding(“iso-8859-1”))
{
而(!rd.EndOfStream)
{
尝试
{
var nextLine=Regex.Replace(rd.ReadLine(),@“\s+”,”);
while(nextLine.Split(“;”)。长度<3)
{
nextLine=nextLine.Replace(“\r\n”,”)+Regex.Replace(rd.ReadLine(),@“\s+”,”);
}
var splits=nextLine.Split(“;”);
DataRow dR=tmp.NewRow();
dR[0]=拆分[0];
dR[1]=拆分[1];
字符串价格=拆分[2];
dR[2]=decimal.Parse(价格,fP);
tmp.Rows.Add(dR);
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
}
}
使用(var conn=db.apri