正如您可能知道的那样,将数据插入表;实体框架"-当您尝试插入大量行时,这种方法非常缓慢。另一种方法是使用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