Заданное значение типа String из источника данных нельзя преобразовать в тип nvarchar указанного целевого столбца. - PullRequest
0 голосов
/ 17 февраля 2020

Я проверил это с явным преобразованием в столбцах с данными и без него, но оно продолжало выдавать исключение System.InvalidOperationException.

К вашему сведению, эти столбцы с typeof (string) все nvarchar в моей базе данных , Я передаю список под названием test , который имеет пользовательский тип.

Изначально я не собирался использовать sqlbulkcopy, но с тех пор, как я перенес на базу данных azure, мне нужен более быстрый запрос вставки.

Буду признателен за любой совет.

var dt = new DataTable();
dt.Columns.Add("LinkID", typeof(string));
dt.Columns.Add("RoadName", typeof(string));
dt.Columns.Add("RoadCategory", typeof(string));
dt.Columns.Add("SpeedBand");
dt.Columns.Add("MinimumSpeed", typeof(string));
dt.Columns.Add("MaximumSpeed", typeof(string));
dt.Columns.Add("StartLatitude");
dt.Columns.Add("StartLongitude");
dt.Columns.Add("EndLatitude");
dt.Columns.Add("EndLongitude");
dt.Columns.Add("Distance", typeof(string));

for (int i = 0; i < test.Count; i++)
{
    dt.Rows.Add(test[i].LinkID, test[i].RoadName, test[i].RoadCategory, 
       test[i].SpeedBand, test[i].MinimumSpeed, test[i].MaximumSpeed, 
       test[i].StartLatitude, test[i].StartLongitude, test[i].EndLatitude, 
       test[i].EndLongitude, test[i].Distance);
}

string sqlConnectionString = "//secret";

using (SqlConnection conn = new SqlConnection(sqlConnectionString))
{
    try
    {
        conn.Open();
    }
    catch (Exception e)
    {
        Debug.WriteLine(e);
    }

    using (var sqlBulk = new SqlBulkCopy(conn))
    {
        //sqlBulk.BatchSize = 1000;
        sqlBulk.DestinationTableName = "dbo.TrafficSpeedBands";

        try
        {
            // Write from the source to the destination.
            sqlBulk.WriteToServer(dt);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 17 февраля 2020

Ваша проблема заключается здесь:

var dt = new DataTable();
//...
dt.Columns.Add("SpeedBand");
//...
dt.Columns.Add("StartLatitude");
dt.Columns.Add("StartLongitude");
dt.Columns.Add("EndLatitude");
dt.Columns.Add("EndLongitude");

По умолчанию метод Add(string columnName) добавляет столбец типа string. Поэтому у вас есть несоответствие типов с базовой таблицей БД, и массовое копирование завершается неудачно. Прочитайте здесь для получения более подробной информации.

Ваше решение с DataAdapter работает, потому что адаптер считывает схему таблицы underyling и устанавливает DataTable с совместимыми типами для вас.

0 голосов
/ 17 февраля 2020

Я перешел на использование адаптера данных, и теперь он работает

string sqlConnectionString = "//secret";

            using (SqlConnection conn = new SqlConnection(sqlConnectionString))
            {
                try
                {
                    conn.Open();
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                }
                Debug.WriteLine("Connection opened");
                var table = new DataTable();

                // read the table structure from the database
                using (var adapter = new SqlDataAdapter($"SELECT TOP 0 * FROM dbo.TrafficSpeedBands", conn))
                {
                    adapter.Fill(table);
                };

                Debug.WriteLine("Filling in rows");
                for (var i = 0; i < test.Count; i++)
                {
                    var row = table.NewRow();
                    row["LinkID"] = test[i].LinkID;
                    row["RoadName"] = test[i].RoadName;
                    row["RoadCategory"] = test[i].RoadCategory;
                    row["SpeedBand"] = test[i].SpeedBand;
                    row["MinimumSpeed"] = test[i].MinimumSpeed;
                    row["MaximumSpeed"] = test[i].MaximumSpeed;
                    row["StartLatitude"] = test[i].StartLatitude;
                    row["StartLongitude"] = test[i].StartLongitude;
                    row["EndLatitude"] = test[i].EndLatitude;
                    row["EndLongitude"] = test[i].EndLongitude;
                    row["Distance"] = test[i].Distance;

                    table.Rows.Add(row);
                }

                using (var sqlBulk = new SqlBulkCopy(conn))
                {
                    Debug.WriteLine("Ready to load live");
                    sqlBulk.DestinationTableName = "dbo.TrafficSpeedBands";

                    try
                    {
                        // Write from the source to the destination.
                        sqlBulk.WriteToServer(table);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }                                        

                    Debug.WriteLine("Done");
                }

                conn.Close();
            }
...