У меня проблема, по-видимому, очень просто, но я не нашел ничего связанного.
public class Fruit
{
public string name { get; set; }
public string color { get; set; }
public string shape { get; set; }
public Image image { get; set; }
}
public class Image
{
public string Id { get; set; }
public string URL { get; set; }
}
Это мой сложный класс, и я хочу преобразовать его в DataTable, чтобы применить SQLBulkCopy, но когда он извлекает класс Image, он передает не значения, а тип данных Image, который вызывает исключение.
public static DataTable ToDataTable<T>(this IList<T> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
Любая подсказка о том, как получить идентификатор свойства Image для выполнения SQLBulkCopy?
Кстати, вот метод, который я использую для вставки:
public static void SaveToDatabase(DataTable data)
{
using (var connection = new SqlConnection(dbConn))
{
SqlTransaction transaction = null;
connection.Open();
try
{
transaction = connection.BeginTransaction();
using (var sqlBulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction))
{
sqlBulkCopy.DestinationTableName = "Fruit";
sqlBulkCopy.ColumnMappings.Add("name", "name");
sqlBulkCopy.ColumnMappings.Add("color", "color");
sqlBulkCopy.ColumnMappings.Add("shape", "shape");
sqlBulkCopy.ColumnMappings.Add("image", "image");
sqlBulkCopy.WriteToServer(data);
}
transaction.Commit();
}
catch (Exception ex) // Here I got the datatype Exception because I don't know how to get the Image.ID value
{
transaction.Rollback();
}
}
}
Очевидно, мой пост немного сбивает с толку, поэтому я собираюсь добавить здесь проблему:
Как получить значения URL и ID из Image класса в следующем коде? В настоящее время он приносит объект Image, который неизвестен, и выдает исключение.
sqlBulkCopy.ColumnMappings.Add("image", "image");
Как их сопоставить? Я знаю, что могу делать это строка за строкой, но мне нужно обрабатывать более 2 миллионов строк при каждом выполнении. Вот почему я пытаюсь использовать массовую копию.
Мне нужно добавить, что эти данные поступают из вызова API в формате Json
SqlBulkCopy
поддерживает только примитивные типы. Чтобы заполнитьVARBINARY(MAX)
столбцы (которые, я надеюсь, вы используете вместо устаревшего типаIMAGE
, имеющего неверно подходящее имя), вам необходимо передатьbyte[]
. Но если вам действительно нужна производительность, вы не хотите возиться с потенциально огромными байтовыми массивами вDataTable
s, а вместо этого хотите передавать данные. Однако это более сложный процесс, поскольку он включает созданиеSqlDataRecord
экземпляров на лету и использованиеSqlBytes
. Вероятно, существуют библиотеки для упрощения этого, но рекомендовать их - это OT на SO. - person Jeroen Mostert   schedule 27.07.2020APIClient<fruit> client = new APIClient<fruit>("fruit", UserName, Password); var retrievedData = client.GetAll(); DataTable data = new DataTable(); data = ToDataTable(retrievedData.Result); SaveToDatabase(data);
- person Weasel   schedule 27.07.2020Image
класс, на самом деле, это не изображение (как в фактических данных растрового изображения наSystem.Drawing.Image
), а всего лишь подобъект из двух столбцов. Независимо от того, как вы вставляете, вы не можете сохранить объект непосредственно в столбце (SQL Server не является базой данных O-O). Вы можете делать такие вещи, как хранить JSON или XML для сериализации данных в столбец, использовать ORM, например Entity Framework (или для чуть менее сложных сценариев Dapper), или просто разделить объект (что в данном случае немного) на два отдельных столбцы. - person Jeroen Mostert   schedule 27.07.2020