C#复杂类插入数百万行

C#复杂类插入数百万行,c#,sqlbulkcopy,C#,Sqlbulkcopy,我有一个问题,显然很简单,但我没有发现任何相关的 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; } pub

我有一个问题,显然很简单,但我没有发现任何相关的

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类中获取URLID值?目前,它带来了未知的对象图像,并引发异常

sqlBulkCopy.ColumnMappings.Add("image", "image");
我如何绘制它们的地图?我知道我可以一行一行地执行,但每次执行时我都要处理200多万行。这就是我为什么要用大容量拷贝的原因


我需要补充的是,该数据来自Json格式的API调用

在修改代码以测试这一点之后,我确实找到了一个解决方案:

if (prop.GetChildProperties().Count > 1)
    row[prop.Name] = (Image)prop.GetValue(item);
else
    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
解决方案只是将GetValue强制转换为Image类,这在ToDataTable方法中应用:

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)
           if (prop.GetChildProperties().Count > 1)
               row[prop.Name] = (Image)prop.GetValue(item);
           else
               row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;

       table.Rows.Add(row);
   }

   return table;
}
公共静态数据表到数据表(此IList数据)
{
PropertyDescriptorCollection属性=TypeDescriptor.GetProperties(typeof(T));
DataTable=新的DataTable();
foreach(属性中的PropertyDescriptor属性)
table.Columns.Add(prop.Name,Nullable.GetUnderlyingType(prop.PropertyType)??prop.PropertyType);
foreach(数据中的T项)
{
DataRow行=table.NewRow();
foreach(属性中的PropertyDescriptor属性)
如果(prop.GetChildProperties().Count>1)
行[prop.Name]=(图像)prop.GetValue(项目);
其他的
行[prop.Name]=prop.GetValue(项)??DBNull.Value;
table.Rows.Add(行);
}
返回表;
}

谢谢大家的时间和帮助

您能否包含将这三个代码片段连接在一起的代码?例如,Fruit和ToDataTable如何使用/传递给SaveToDatabase函数?
SqlBulkCopy
仅支持基本类型。要填充
VARBINARY(MAX)
列(我希望您使用的是
IMAGE
类型,该类型的名称令人误解),您需要传递一个
byte[]
。但是,如果您确实需要性能,您不想在
DataTable
s中摆弄可能很大的字节数组,而是流式传输数据。但是,这更复杂,因为它涉及动态构造
SqlDataRecord
实例并使用
SqlBytes
。可能有一些库可以简化这一点,但推荐的是OT。感谢您的回复:@RBarryYoung:
APIClient client=new APIClient(“fruit”,用户名,密码);var retrievedData=client.GetAll();DataTable数据=新DataTable();data=ToDataTable(retrievedData.Result);保存到数据库(数据)
@Jeroenmoster感谢您的回复:我同意您的说法名称不正确,我应该使用Picture作为类而不是Image,我不想存储和Image数据类型,而是水果的图片细节,在这种情况下,图片的ID和URL Whoops,我完全错过了您的
Image
类,实际上,图像(如中所示,每个
System.Drawing.image
)的实际位图数据),只是两列的子实体。无论如何插入,都不能将对象直接存储在列中(SQL Server不是O-O数据库)。您可以执行诸如存储JSON或XML之类的操作,将数据序列化到一列中,使用类似ORM的实体框架(或者对于稍微不太复杂的场景,可以使用Dapper),或者只将“对象”(在本例中并不多)拆分为两个单独的列。
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)
           if (prop.GetChildProperties().Count > 1)
               row[prop.Name] = (Image)prop.GetValue(item);
           else
               row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;

       table.Rows.Add(row);
   }

   return table;
}