Откакто направих кратък коментар по въпроса ви, имах възможност да си поиграя напълно с опциите. Изглежда, че в момента (дори да опитвате .NET 4.6 и SQL 2014) не можете да зададете SqlGeography
ИЛИ SqlGeometry
като typeof()
параметър при дефиниране на колона за DataTable
. За абсолютна яснота можете да го направите в .NET и дори да го попълните, но след това не можете да предадете тази таблица като TVP към съхранена процедура.
Има две опции.
Опция 1. Предайте стойността във формат WKT.
Определете вашия тип таблица, както следва.
CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
[geom] [varchar](max) NOT NULL
)
След това дефинирайте своята съхранена процедура, както следва.
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
Дефинирайте вашата .NET DataTable по следния начин:
DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));
Попълнете го, както следва:
for (int j = 0; j < geometryCollection.Count; j++)
{
System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();
wktTable.Rows.Add(wkt.ToString());
}
Опция 2. Предайте стойността във формат WKB.
Определете вашия тип таблица, както следва.
CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
[geom] [varbinary](max) NOT NULL
)
След това дефинирайте своята съхранена процедура, както следва.
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
Дефинирайте вашата .NET DataTable по следния начин:
DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));
Попълнете го, както следва:
for (int j = 0; j < geometryCollection.Count; j++)
{
wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}
Бележки:
Дефинирайте вашия SqlParameter както следва:
SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;
Оставил съм SRID от 4326 от работата си по география. Можете да промените това на каквото пожелаете - и наистина, ако използвате Geography
Предлагам да го направите като втори параметър, за да имате гъвкавост.
Освен това, ако производителността е критична, ще откриете, че използването на WKB е по-добро. Моите тестове установиха, че WKB завърши за 45% до 65% от времето, необходимо за WKT. Това ще варира в зависимост от сложността на вашите данни и от вашата настройка.
Информацията, която сте намерили при указване на UdtTypeName
на параметъра като "Геометрия" / "География" е правилно, когато вашата Съхранена процедура има параметър от тип [Геометрия] или [География]. Не се отнася за TVP.