C# SqlBulkCopy 错过一行

C# SqlBulkCopy miss a row

我正在使用 SqlBulkCopy 将数据从 excel 和另一个数据库导入到 2 个不同的 SQL 表中。

一切顺利,直到我设法在目标表中每次丢失一行时,来自 excel 或其他数据库的源。

这是从 excel 导入数据的代码片段:

 public void ImportDataFromExcel(string excelFilePath)
    {
        string ssqltable = "szip_IncomingAssetData";
        string myexceldataquery = "SELECT * FROM ["+ GetExcelSheetNames(excelFilePath)+"]";
        try
        {

            string sexcelconnectionstring = GetExcelConnectionString(excelFilePath);
            Logger.Log("Excel Connection String: " + sexcelconnectionstring, false);


            OpenDatabaseConnection(1, "ImportDataFromExcel");

            OleDbConnection oledbconn = new OleDbConnection(sexcelconnectionstring);
            OleDbCommand oledbcmd = new OleDbCommand(myexceldataquery, oledbconn);

            oledbconn.Open();
            OleDbDataReader dr = oledbcmd.ExecuteReader();
            SqlBulkCopy bulkcopy = new SqlBulkCopy(hpamConnection)
            {
                DestinationTableName = ssqltable
            };

            SqlBulkCopyColumnMapping mapID = new SqlBulkCopyColumnMapping(System.Configuration.ConfigurationManager.AppSettings["szip_AssetID"], "szip_IncomingAssetID");
            SqlBulkCopyColumnMapping mapName = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetName"], "szip_IncomingAssetName");
            SqlBulkCopyColumnMapping mapSerial = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetSerial"], "szip_IncomingAssetSerial");
            SqlBulkCopyColumnMapping mapRI = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetRI"], "szip_IncomingAssetRI");
            SqlBulkCopyColumnMapping mapModel = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetModel"],"szip_IncomingAssetModel");
            SqlBulkCopyColumnMapping mapVendor = new SqlBulkCopyColumnMapping(System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetVendor"],"szip_IncomingAssetVendor");
            SqlBulkCopyColumnMapping mapFRU = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetFirstRU"], "szip_IncomingAssetFirstRU");
            SqlBulkCopyColumnMapping mapLRU = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetLastRU"], "szip_IncomingAssetLastRU");
            SqlBulkCopyColumnMapping mapLocation = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetLocation"], "szip_IncomingAssetLocation");
            SqlBulkCopyColumnMapping mapRack = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetRack"], "szip_IncomingAssetRack");
            SqlBulkCopyColumnMapping mapStatus = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetStatus"], "szip_IncomingAssetStatus");
            SqlBulkCopyColumnMapping mapConfig = new SqlBulkCopyColumnMapping(System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetConfig"], "szip_IncomingAssetConfig");
            SqlBulkCopyColumnMapping mapIPDNS = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetIP_DNSname"], "szip_IncomingAssetIP_DNSname");
            SqlBulkCopyColumnMapping mapArea = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetArea"], "szip_IncomingAssetArea");
            SqlBulkCopyColumnMapping mapContact = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetContact"], "szip_IncomingAssetContact");
            SqlBulkCopyColumnMapping mapExtension = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetExtension"], "szip_IncomingAssetExtension");
            SqlBulkCopyColumnMapping mapHWType = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetHardwareType"], "szip_IncomingAssetHardwareType");
            SqlBulkCopyColumnMapping mapConnections = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetCurrentConnections"], "szip_IncomingAssetCurrentConnections");
            SqlBulkCopyColumnMapping mapMaxConnections = new SqlBulkCopyColumnMapping( System.Configuration.ConfigurationManager.AppSettings["szip_IncomingAssetMaxConnections"], "szip_IncomingAssetMaxConnections");

            bulkcopy.ColumnMappings.Add(mapID);
            bulkcopy.ColumnMappings.Add(mapName);
            bulkcopy.ColumnMappings.Add(mapSerial);
            bulkcopy.ColumnMappings.Add(mapRI);
            bulkcopy.ColumnMappings.Add(mapModel);
            bulkcopy.ColumnMappings.Add(mapVendor);
            bulkcopy.ColumnMappings.Add(mapFRU);
            bulkcopy.ColumnMappings.Add(mapLRU);
            bulkcopy.ColumnMappings.Add(mapLocation);
            bulkcopy.ColumnMappings.Add(mapRack);
            bulkcopy.ColumnMappings.Add(mapStatus);
            bulkcopy.ColumnMappings.Add(mapConfig);
            bulkcopy.ColumnMappings.Add(mapIPDNS);
            bulkcopy.ColumnMappings.Add(mapArea);
            bulkcopy.ColumnMappings.Add(mapContact);
            bulkcopy.ColumnMappings.Add(mapExtension);
            bulkcopy.ColumnMappings.Add(mapHWType);
            bulkcopy.ColumnMappings.Add(mapConnections);
            bulkcopy.ColumnMappings.Add(mapMaxConnections);

            while (dr.Read())
            {
                  bulkcopy.WriteToServer(dr);
            }
            dr.Close();
            oledbconn.Close();
            CloseDatabaseConnection(1, "ImportDataFromExcel");
            Logger.Log("Data Imported from Excel to Database", false);
        }
        catch (Exception e)
        {
           Logger.Log("Cannot Read Excel File: " + e.Message.ToString(), true); 

        }

连接字符串如下:

private string GetExcelConnectionString(string excelfile)
    {
        Dictionary<string, string> props = new Dictionary<string, string>
        {
            ["Provider"] = "Microsoft.ACE.OLEDB.12.0",
            ["Extended Properties"] = "'Excel 12.0 XML;HDR=YES'",
            ["Data Source"] = excelfile
        };


        StringBuilder sb = new StringBuilder();

        foreach (KeyValuePair<string, string> prop in props)
        {
            sb.Append(prop.Key);
            sb.Append('=');
            sb.Append(prop.Value);
            sb.Append(';');
        }

        return sb.ToString();
    }

在从其他数据库导入到我的应用程序数据库的情况下:

public void ImportSmartZoneAssetData()
    {

        SqlConnection hpamConnection = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["hpamConnectionString"]);
        SqlConnection smartZoneConnection = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["szConnectionString"]);

        string sqlCommand = "select i.pa_deviceid as DeviceID, " +
                            "i.pa_displayname as DeviceName, " +
                            "j.PA_MATERIALIZEDSTRPATH as [Location], " +
                            "k.PA_CONTAINERTYPEID as ContainerTypeID, " +
                            "l.PA_CONTAINERTYPEDESCRIPTION as ContainerType, " +
                            "k.PA_DISPLAYNAME as ContainerName, " +
                            "i.PA_CONTAINERPOSITION as FirstRU, " +
                            "(select pa_assetvalue from PA_ASSETLIST where PA_PARENTID = i.PA_DEVICEID and PA_ASSETATTRIBUTEID = 24) as SerialNumber, " +
                            "(select pa_assetvalue from PA_ASSETLIST where PA_PARENTID = i.PA_DEVICEID and PA_ASSETATTRIBUTEID = 25) as BarCode " +
                            "from pa_device i " +
                            "left join PA_LOCATION j on i.pa_locationid = j.PA_LOCATIONID " +
                            "left join PA_CONTAINER k on i.PA_CONTAINERID = k.PA_CONTAINERID " +
                            "left join PA_CONTAINERTYPE l on k.PA_CONTAINERTYPEID = l.PA_CONTAINERTYPEID";

        string ssqltable = "szip_SmartZoneAssetData";

        SqlBulkCopy bulkcopy = new SqlBulkCopy(hpamConnection)
        {
            DestinationTableName = ssqltable
        };
        SqlDataReader myReader = null;
        SqlCommand myCommand = new SqlCommand(sqlCommand, smartZoneConnection);
        hpamConnection.Open();
        smartZoneConnection.Open();
        myReader = myCommand.ExecuteReader();
        while (myReader.Read())
        {
            bulkcopy.WriteToServer(myReader);
        }
        Logger.Log("Imported Records from SmartZone: " + GetRowsCopied(bulkcopy), false);
        myReader.Close();
        hpamConnection.Close();
        smartZoneConnection.Close();
        Logger.Log("Data Imported from SmartZone to Database", false);
    }
}

我想知道代码是否有问题,以及为什么我在两种情况下总是丢失一条并且只有一条记录。

/***************************

在这两种情况下都去掉了 "while (myReader.Read())",现在可以完美运行了。新代码是:

myReader = myCommand.ExecuteReader();
        try
        {
            bulkcopy.WriteToServer(myReader);
        }
        catch (Exception e)
        {
            Logger.Log("Cannot Import SmartZone Device Data: " + e.Message, true);
        }

谢谢 :-)

正如所建议的那样,while (myReader.Read()) 正在推进一个寄存器。

我在这两种情况下都摆脱了 "while (myReader.Read())",现在它完美无缺。新代码是:

myReader = myCommand.ExecuteReader();
    try
    {
        bulkcopy.WriteToServer(myReader);
    }
    catch (Exception e)
    {
        Logger.Log("Cannot Import SmartZone Device Data: " + e.Message, true);
    }

谢谢 :-)