Desde que fiz um breve comentário sobre sua pergunta, tive a chance de brincar completamente com as opções. Parece que no momento (mesmo tentando .NET 4.6 e SQL 2014) você não pode definir
SqlGeography
OU SqlGeometry
como o typeof()
parâmetro ao definir uma coluna para um DataTable
. Para maior clareza, você pode fazer isso em .NET e até preenchê-lo, mas não pode passar essa tabela como um TVP para um procedimento armazenado. Existem duas opções.
Opção 1. Passe o valor no formato WKT.
Defina seu tipo de tabela da seguinte maneira.
CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
[geom] [varchar](max) NOT NULL
)
Em seguida, defina seu procedimento armazenado da seguinte maneira.
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 seu .NET DataTable da seguinte forma:
DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));
Preencha-o da seguinte forma:
for (int j = 0; j < geometryCollection.Count; j++)
{
System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();
wktTable.Rows.Add(wkt.ToString());
}
Opção 2. Passe o valor no formato WKB.
Defina seu tipo de tabela da seguinte maneira.
CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
[geom] [varbinary](max) NOT NULL
)
Em seguida, defina seu procedimento armazenado da seguinte maneira.
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 seu .NET DataTable da seguinte forma:
DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));
Preencha-o da seguinte forma:
for (int j = 0; j < geometryCollection.Count; j++)
{
wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}
Observações:
Defina seu SqlParameter da seguinte forma:
SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;
Deixei um SRID de 4326 no meu trabalho de geografia. Você pode alterar isso para o que quiser - e, de fato, se estiver usando
Geography
Eu sugeriria torná-lo um segundo parâmetro para lhe dar flexibilidade. Além disso, se o desempenho for crítico, você achará melhor usar o WKB. Meus testes descobriram que o WKB foi concluído em 45% a 65% do tempo que o WKT levou. Isso varia de acordo com a complexidade de seus dados e sua configuração.
As informações que você encontrou ao especificar o
UdtTypeName
do parâmetro como "Geometria" / "Geography" está correto quando seu Stored Procedure tem um parâmetro do tipo [Geometry] ou [Geography]. Não se aplica a TVPs.