在.NET Core中使用NTS几何图形进行大容量插入



正如您可能知道的那样,将数据插入表;实体框架"-当您尝试插入大量行时,这种方法非常缓慢。另一种方法是使用SqlBulkCopy,它在提高性能方面做得很好。问题是SqlBulkCopy(根据我阅读和测试的内容(不支持.NET Core中的SQL几何体类型。

这是在EF Core中,C#属性类型是无法更改的NTS几何体。

使用旧库Microsoft.SqlServer.Types不是一个选项,因为它们在.NET Core中不起作用。数据当前作为NTS几何图形从另一个SQL Server数据库加载。

有人找到插入多行的有效方法了吗?

免责声明:我是linq2db和扩展linq2db.EntityFrameworkCore 的创建者之一

linq2db本身并没有对NetTopologySuite的依赖关系,所以库应该知道如何转换这些类型。为每个应用程序配置一次(我希望涵盖所有内容(:

var writer = new NetTopologySuite.IO.SqlServerBytesWriter() { IsGeography = true };
MappingSchema.Default.SetConverter<Point, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<Polygon, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<GeometryCollection, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<LinearRing, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<LineString, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<MultiLineString, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<MultiPoint, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));
MappingSchema.Default.SetConverter<MultiPolygon, DataParameter>(p => new DataParameter(null, writer.Write(p), DataType.Udt));

然后,您可以将BulkCopy用于具有任何Geometry属性的任何实体:

context.BulkCopy(someEntities);

免责声明:我是实体框架扩展的所有者

正如您可能知道的那样,将数据插入表;实体框架"-的速度非常慢

这是真的,这也是我们创建库(付费库(的主要原因。

我们的库通过实体框架支持context.BulkInsert,也支持SQL Geometries


也就是说,这也可以直接通过SqlBulkCopy来实现。

对于EF Core,您需要使用SqlServerBytesWriter转换您的价值。

下面是一个完整的例子:

var list = // your list
var byteWriterGeometry = new NetTopologySuite.IO.SqlServerBytesWriter();
var byteWriterGeographgy = new NetTopologySuite.IO.SqlServerBytesWriter() { IsGeography = true };
var dt = new DataTable();
dt.Columns.Add("Geometry", typeof(object));
dt.Columns.Add("Point", typeof(object));
list.ForEach(x =>
{
dt.Rows.Add(byteWriterGeometry.Write(x.Geometry), byteWriterGeographgy.Write(x.Point));
});
var connection = new SqlConnection("your connection string");
connection.Open();
var bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "your table name";
bulkCopy.ColumnMappings.Add("Geometry", "Geometry");
bulkCopy.ColumnMappings.Add("Point", "Point");              
bulkCopy.WriteToServer(dt);

使用NetTopologySuite实体(类型为geometry、geography(进行批量插入的关键是:

  • 将数据表的列类型设置为object(或将实体的属性类型设置为object(
  • dtTable.Columns.Add("Shape", typeof(Object)); //force object
  • 使用NetTopologySuite.IO.SqlServerBytesWriter((对象将形状转换为字节数组(byte[](,并将对象列/属性设置为此字节数组
  • var byteWriterGeometry = new NetTopologySuite.IO.SqlServerBytesWriter(); dataRow["geometry"] = byteWriteGeometry.Write(shape);

这里有一个使用神奇的Z.BulkOperations库的dotnetfiddle,它演示了这一点:https://dotnetfiddle.net/DZiQJG

相关内容

  • 没有找到相关文章

最新更新