sql >> Databáze >  >> RDS >> Sqlserver

Datatable obsahující SqlGeometry způsobuje selhání provádění uložené procedury... Proč?

Od chvíle, kdy jsem napsal krátký komentář k vaší otázce, jsem měl možnost si plně pohrát s možnostmi. Zdá se, že v současné době (i při pokusu o .NET 4.6 a SQL 2014) nemůžete nastavit SqlGeography NEBO SqlGeometry jako typeof() parametr při definování sloupce pro DataTable . Pro absolutní přehlednost to můžete udělat v .NET a dokonce ji naplnit, ale pak nemůžete předat tuto tabulku jako TVP do uložené procedury.

Existují dvě možnosti.

Možnost 1. Předejte hodnotu ve formátu WKT.

Definujte svůj typ tabulky následovně.

CREATE TYPE [dbo].[WKT_Example] AS TABLE
(
    [geom] [varchar](max) NOT NULL
)

Poté definujte uloženou proceduru následovně.

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

Definujte svůj .NET DataTable následovně:

DataTable wktTable = new DataTable();
wktTable.Columns.Add("SpatialData", typeof(string));

Vyplňte jej následovně:

for (int j = 0; j < geometryCollection.Count; j++)
{
    System.Data.SqlTypes.SqlString wkt = geometryCollection[j].STAsText().ToSqlString();

    wktTable.Rows.Add(wkt.ToString());
}

Možnost 2. Předejte hodnotu ve formátu WKB.

Definujte svůj typ tabulky následovně.

CREATE TYPE [dbo].[WKB_Example] AS TABLE
(
    [geom] [varbinary](max) NOT NULL
)

Poté definujte uloženou proceduru následovně.

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

Definujte svůj .NET DataTable následovně:

DataTable wkbTable = new DataTable();
wkbTable.Columns.Add("SpatialData", typeof(System.Data.SqlTypes.SqlBytes));

Vyplňte jej následovně:

for (int j = 0; j < geometryCollection.Count; j++)
{
    wkbTable.Rows.Add(geographyCollection[j].STAsBinary());
}

Poznámky:

Definujte svůj SqlParameter následovně:

SqlParameter p = new SqlParameter("@rows", SqlDbType.Structured);
p.TypeName = "WKB_Example"; // The name of your table type
p.Value = wkbTable;

Zanechal jsem SRID 4326 in z mé zeměpisné práce. Můžete to změnit na cokoli chcete - a skutečně, pokud používáte Geography Navrhoval bych, aby to byl druhý parametr, který vám poskytne flexibilitu.

Navíc, pokud je výkon kritický, zjistíte, že používání WKB bude lepší. Moje testy zjistily, že WKB dokončil za 45 % až 65 % času, který WKT zabral. To se bude lišit podle složitosti vašich dat a vašeho nastavení.

Informace, které jste našli při zadání parametru UdtTypeName jako "Geometrie" / "Geografie" je správné, pokud má vaše uložená procedura parametr typu [Geometrie] nebo [Geografie]. Nevztahuje se na TVP.



  1. Nenašel jsem žádnou chybu. Tento kód funguje dobře. Dokonale aktualizujte moje data, ale zobrazuje se 1 chyba

  2. Jak se vyhnout sporu databáze při ručním zvyšování PK nového řádku

  3. Vyberte příkaz pro návrat nadřazeného a nekonečného potomka

  4. Existuje nějaký způsob, jak vložit sestavy a řídicí panely power bi do vb.net nebo C# desktopové aplikace s databází sql server 2008?