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