Desde que hice un breve comentario sobre su pregunta, tuve la oportunidad de jugar completamente con las opciones. Parece que en la actualidad (incluso probando .NET 4.6 y SQL 2014) no puede configurar SqlGeography
O SqlGeometry
como el typeof()
parámetro al definir una columna para un DataTable
. Para una claridad absoluta, puede hacerlo en .NET e incluso completarlo, pero luego no puede pasar esa tabla como un TVP a un procedimiento almacenado.
Hay dos opciones.
Opción 1. Pasar el valor en formato WKT.
Defina su tipo de tabla de la siguiente manera.
CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
[geom] [varchar](max) NOT NULL
)
Luego defina su procedimiento almacenado de la siguiente manera.
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
Defina su tabla de datos .NET de la siguiente manera:
DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));
Rellénelo de la siguiente manera:
for (int j = 0; j < geometryCollection.Count; j++)
{
System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();
wktTable.Rows.Add(wkt.ToString());
}
Opción 2. Pasar el valor en formato WKB.
Defina su tipo de tabla de la siguiente manera.
CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
[geom] [varbinary](max) NOT NULL
)
Luego defina su procedimiento almacenado de la siguiente manera.
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
Defina su tabla de datos .NET de la siguiente manera:
DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));
Rellénelo de la siguiente manera:
for (int j = 0; j < geometryCollection.Count; j++)
{
wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}
Notas:
Defina su SqlParameter de la siguiente manera:
SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;
Dejé un SRID de 4326 de mi trabajo de geografía. Puede cambiar esto a lo que desee, y de hecho si está usando Geography
Sugeriría convertirlo en un segundo parámetro para darle flexibilidad.
Además, si el rendimiento es crítico, encontrará que usar WKB es mejor. Mis pruebas encontraron que WKB completó en 45% a 65% del tiempo que tomó WKT. Esto variará según la complejidad de sus datos y su configuración.
La información que encontró al especificar el parámetro UdtTypeName
como "Geometría" / "Geografía" es correcto cuando su Procedimiento almacenado tiene un parámetro de tipo [Geometría] o [Geografía]. No se aplica a los TVP.