c# - 使用 SqlBulkCopy 和 DbGeography 数据类型插入大量数据
问题描述
我正在使用 SqlBulkCopy 将 10 000 多条记录插入到我的数据库中,但由于 DbGeography 点,它不起作用。
我不断收到一条被抛出的异常消息:
“指定类型未在目标服务器上注册。System.Data.Entity.Spatial.DbGeography”。
这是我的代码。
public void AddBulkRange(string tableName, List<TEntity> entities)
{
using (var context = new TContext())
{
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
string conectionString = context.Database.Connection.ConnectionString;
using (var connection = new SqlConnection(conectionString))
{
connection.Open();
SqlTransaction transaction = connection.BeginTransaction();
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
{
bulkCopy.BatchSize = 2000;
bulkCopy.DestinationTableName = "dbo." + tableName;
try
{
DataTable data = DataReaderConverterHelper.ToDataTable(entities);
//This just explicitly maps the columns in sqlBulkCopy to the table columns
foreach (DataColumn column in data.Columns)
{
bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(column.ColumnName, column.ColumnName));
}
bulkCopy.WriteToServer(data);
}
catch (Exception e)
{
transaction.Rollback();
connection.Close();
}
}
transaction.Commit();
}
}
}
这是 ToDataTable 方法。
public static DataTable ToDataTable<TEntity>(this IList<TEntity> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(TEntity));
DataTable dt = new DataTable();
for (int i = 0; i < properties.Count; i++)
{
PropertyDescriptor property = properties[i];
dt.Columns.Add(property.Name, Nullable.GetUnderlyingType(
property.PropertyType) ?? property.PropertyType);
}
object[] values = new object[properties.Count];
foreach (TEntity item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = properties[i].GetValue(item);
}
dt.Rows.Add(values);
}
return dt;
}
问题是 DbGeography 点正在引发异常。
我的模型中的字段类型。
public System.Data.Entity.Spatial.DbGeography geography_point { get; set; }
在数据库中,字段类型是地理。
如果我使用下面的方法,我可以插入,但问题是我得到一个超时错误,这就是我想使用 SqlBulkCopy 的原因,但正如我上面所说,它因为一种数据类型而不起作用。
public List<TEntity> AddRange(List<TEntity> entities)
{
int takeCount = 100;
int counter = (entities.Count % takeCount) == 0
? (entities.Count / takeCount)
: (entities.Count / takeCount) + 1;
for (int i = 0; i < counter; i++)
{
using (var context = new TContext())
{
List<TEntity> subList = entities.Skip(i * takeCount).Take(takeCount).ToList();
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;
context.Set<TEntity>().AddRange(subList);
context.SaveChanges();
context.Dispose();
}
}
return entities;
}
解决方案
感谢@AlwaysLearning 的一些输入,我做了一些更改并让 DbGeography 与数据表一起工作。
public static DataTable ToDataTable<TEntity>(this IList<TEntity> data)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(TEntity));
DataTable dt = new DataTable();
for (int i = 0; i < properties.Count; i++)
{
PropertyDescriptor property = properties[i];
if (property.PropertyType.Name == "DbGeography")
{
dt.Columns.Add(property.Name, typeof(SqlGeography));
continue;
}
dt.Columns.Add(property.Name, Nullable.GetUnderlyingType(
property.PropertyType) ?? property.PropertyType);
}
object[] values = new object[properties.Count];
foreach (TEntity item in data)
{
for (int i = 0; i < 20; i++)
{
if (properties[i].PropertyType.Name == "DbGeography")
{
DbGeography Point = (DbGeography)properties[i].GetValue(item);
SqlGeography newGeography = SqlGeography.Parse(Point.AsText()).MakeValid();
values[i] = newGeography;
continue;
}
values[i] = properties[i].GetValue(item);
}
dt.Rows.Add(values);
}
return dt;
}
我所做的只是将 DbGeography 数据类型转换为 SqlGeography 类型,它运行良好。
推荐阅读
- c++ - Xcode 语义问题 refdefenition 或先前定义的代码
- tabulator - 在制表符网格中读取分块 JSON 流
- python - 不同拟合类型的 scipy.odr 输出不一致?
- javascript - Stripe webhook 返回 400 响应
- coldfusion - 在搜索之前获得额外的 OR
- ruby-on-rails - Rails:如何在仅 API 的应用程序中停止请求周期?
- android - Android UnifiedNativeAds 导致内存泄漏
- ruby - 在Ruby中循环更新切片的一部分
- postgresql - Hasura中纬度/经度的几何功能不起作用
- c++ - 根据 C++ 标准的定义实现 `is_similar` 类型特征