Utilizzo di Dapper con SQL Spatial Types come parametro

dapper orm spatial sql-server-2008

Domanda

Ho un sistema che fondamentalmente deve fare una query come questa:

SELECT * FROM MyTable WHERE @parameter.STIntersects(MyGeometryColumn)

Questo è abbastanza semplice da fare quando si usano i parametri SQL vanilla, basta creare il parametro in un modo non tipico (dove la variabile del builder è SqlGeometryBuilder che utilizzo per creare un rettangolo):

command.Parameters.Add(new SqlParameter
{
    UdtTypeName = "geometry",
    Value = builder.ConstructedGeometry,
    ParameterName = "@paremeter"
});

Ora, quando provo a farlo usando dapper, ottengo un errore che non riesce a capire come usarlo come parametro. Chiunque abbia funzionato, o qualche suggerimento su come abilitarlo? Ho una soluzione alternativa, ma ciò implica l'utilizzo della rappresentazione della stringa e la conversione in un tipo di geometria nella mia query SQL. Io davvero non lo voglio.

Per rispondere al commento, l'errore che sto ottenendo è "Il parametro membro di tipo Microsoft.SqlServer.Types.SqlGeometry non può essere utilizzato come valore di parametro". In altre parole, dapper non sa come gestire un oggetto SqlGeometry come parametro.

Risposta accettata

La chiave per implementare parametri DB specifici e meravigliosi si riduce a SqlMapper.IDynamicParameters

Questa semplice interfaccia ha un singolo endpoint:

public interface IDynamicParameters
{
    void AddParameters(IDbCommand command);
}

Dapper ha già un'implementazione generica di DB di questa interfaccia chiamata: DynamicParameters che consente di gestire i valori di output e di ritorno.

Per emulare questa roba spaziale proverei qualcosa come:

public class SpatialParam : SqlMapper.IDynamicParameters
{
    string name; 
    object val;

    public SpatialParam(string name, object val)
    {
       this.name = name; 
       this.val = val;
    }

    public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
    {
       var sqlCommand = (SqlCommand)command;
       sqlCommand.Parameters.Add(new SqlParameter
       {
          UdtTypeName = "geometry",
          Value = val,
          ParameterName = name
       });
    }
}

Uso:

cnn.Query("SELECT * FROM MyTable WHERE @parameter.STIntersects(MyGeometryColumn)",
  new SpatialParam("@parameter", builder.ConstructedGeometry));

Questa semplice implementazione dell'interfaccia gestisce solo un singolo parametro, ma può essere facilmente estesa per gestire più parametri, passando dal costruttore o aggiungendo un metodo AddParameter helper.


Risposta esperta

  • Dapper.EntityFramework 1.26 ha il supporto per DbGeography
  • Dapper 1.32 ha il supporto integrato per SqlGeography
  • Dapper 1.33 ha il supporto integrato per SqlGeometry
  • Dapper.EntityFramework 1.33 ha il supporto integrato per DbGeometry
  • Dapper 1.34 ha il supporto integrato per SqlHierarchyId

Quindi con le ultime librerie; dovrebbe semplicemente funzionare.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché