Odkąd skomentowałem twoje pytanie, miałem okazję w pełni pobawić się opcjami. Wygląda na to, że obecnie (nawet próbując .NET 4.6 i SQL 2014) nie można ustawić SqlGeography
LUB SqlGeometry
jako typeof()
parametr podczas definiowania kolumny dla DataTable
. Aby uzyskać absolutną przejrzystość, możesz to zrobić w .NET, a nawet wypełnić ją, ale wtedy nie możesz przekazać tej tabeli jako TVP do procedury przechowywanej.
Istnieją dwie opcje.
Opcja 1. Przekaż wartość w formacie WKT.
Zdefiniuj typ tabeli w następujący sposób.
CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
[geom] [varchar](max) NOT NULL
)
Następnie zdefiniuj procedurę składowaną w następujący sposób.
CREATE PROCEDURE [dbo].[BulkInsertFromWKT]
@rows [dbo].[WKT_Example] READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO [dbo].[Table1]
([SpatialData])
SELECT
geometry::STGeomFromText(R.[SpatialData], 4326)
FROM
@rows R;
END
Zdefiniuj swoją tabelę danych .NET w następujący sposób:
DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));
Wypełnij go w następujący sposób:
for (int j = 0; j < geometryCollection.Count; j++)
{
System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();
wktTable.Rows.Add(wkt.ToString());
}
Opcja 2. Przekaż wartość w formacie WKB.
Zdefiniuj typ tabeli w następujący sposób.
CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
[geom] [varbinary](max) NOT NULL
)
Następnie zdefiniuj procedurę składowaną w następujący sposób.
CREATE PROCEDURE [dbo].[BulkInsertFromWKB]
@rows [dbo].[WKB_Example] READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO [dbo].[Table1]
([SpatialData])
SELECT
geometry::STGeomFromWKB(R.[SpatialData], 4326)
FROM
@rows R;
END
Zdefiniuj swoją tabelę danych .NET w następujący sposób:
DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));
Wypełnij go w następujący sposób:
for (int j = 0; j < geometryCollection.Count; j++)
{
wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}
Uwagi:
Zdefiniuj swój SqlParameter w następujący sposób:
SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;
Zostawiłem SRID 4326 w mojej pracy z geografii. Możesz to zmienić na co chcesz - i rzeczywiście, jeśli używasz Geography
Sugerowałbym, aby był to drugi parametr, aby zapewnić elastyczność.
Dodatkowo, jeśli wydajność jest krytyczna, lepiej będzie używać WKB. Moje testy wykazały, że WKB ukończono w 45% do 65% czasu, jaki zajęło WKT. Zależy to od złożoności danych i konfiguracji.
Informacje znalezione podczas określania parametru UdtTypeName
jako „Geometria” / „Geografia” jest poprawna, gdy procedura składowana ma parametr typu [Geometry] lub [Geography]. Nie dotyczy to TVP.