sql >> Database >  >> RDS >> Sqlserver

Een datatabel met SqlGeometry zorgt ervoor dat de uitvoering van de opgeslagen procedure mislukt... Waarom?

Sinds ik een korte opmerking heb gemaakt over uw vraag, heb ik de kans gehad om volledig met de opties te spelen. Het lijkt erop dat je op dit moment (zelfs als je .NET 4.6 en SQL 2014 probeert) SqlGeography niet kunt instellen OF SqlGeometry als de typeof() parameter bij het definiëren van een kolom voor een DataTable . Voor alle duidelijkheid:je kunt het in .NET doen en zelfs invullen, maar dan kun je die tabel niet als TVP doorgeven aan een Stored Procedure.

Er zijn twee opties.

Optie 1. Geef de waarde door in WKT-formaat.

Definieer uw tabeltype als volgt.

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

Definieer vervolgens uw Opgeslagen Procedure als volgt.

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

Definieer uw .NET-gegevenstabel als volgt:

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

Vul het als volgt in:

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

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

Optie 2. Geef de waarde door in WKB-indeling.

Definieer uw tabeltype als volgt.

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

Definieer vervolgens uw Opgeslagen Procedure als volgt.

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

Definieer uw .NET-gegevenstabel als volgt:

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

Vul het als volgt in:

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

Opmerkingen:

Definieer uw SqlParameter als volgt:

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

Ik heb een SRID van 4326 achtergelaten van mijn aardrijkskundewerk. Je kunt dit veranderen in wat je maar wilt - en inderdaad als je Geography gebruikt Ik zou willen voorstellen om er een tweede parameter van te maken om je flexibiliteit te geven.

Bovendien, als de prestaties van cruciaal belang zijn, zult u merken dat het gebruik van WKB beter is. Uit mijn tests bleek dat WKB in 45% tot 65% van de tijd die WKT in beslag nam, voltooide. Dit is afhankelijk van de complexiteit van uw gegevens en uw instellingen.

De informatie die u hebt gevonden bij het specificeren van de parameter UdtTypeName als "Geometry" / "Geography" correct is wanneer uw opgeslagen procedure een parameter van het type [Geometry] of [Geography] heeft. Het is niet van toepassing op TVP's.



  1. Converteer 'datetime' naar 'date' in SQL Server (T-SQL-voorbeelden)

  2. Postgres jsonb-query op genest object

  3. Rijen verwijderen die overeenkomen met subtekenreeks met LIKE?

  4. MySQL, DELETE Query met een Join