2011-07-14 11 views
8

Tengo un sistema que básicamente tiene que hacer una consulta como esta:Dapper con tipos espaciales de SQL como parámetro

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

Esto es bastante fácil de hacer cuando se utilizan parámetros de vainilla SQL, sólo hay para crear su parámetro de una manera atípica (donde la variable constructor es un SqlGeometryBuilder que utilizo para crear un rectángulo):

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

Ahora, Cuando trato de hacer esto utilizando apuesto, me sale un error que no puede entender cómo usar esto como un parámetro. ¿Alguien que tiene esto funcionando, o algún indicador sobre cómo habilitar esto? Tengo una solución alternativa, pero eso implica el uso de la representación de cadena y convertir eso a un tipo de geometría en mi consulta SQL. Realmente no quiero eso.

Para responder al comentario, el error que obtengo es 'El parámetro miembro de tipo Microsoft.SqlServer.Types.SqlGeometry no se puede usar como valor de parámetro'. En otras palabras, dapper no sabe cómo tratar con un objeto SqlGeometry como parámetro.

+0

¿Cuál es el error que está recibiendo? –

Respuesta

10

La clave para implementar params específicos DB extraños y maravillosos todo se reduce a SqlMapper.IDynamicParameters

Esta interfaz simple tiene un único criterio de valoración:

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

Dapper ya tiene una implementación genérica DB de esta interfaz llamada: DynamicParameters que le permite manejar los valores de salida y retorno.

emular esta materia espacial me gustaría probar algo como:

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)); 

Esta sencilla implementación de la interfaz maneja un solo parámetro, pero puede fácilmente extenderse para manejar múltiples params, ya sea al pasar desde el constructor o agregar un método auxiliar AddParameter.

+0

¡Funciona perfectamente!Gracias :) –

+0

NOTA: La versión actual de Dapper (a partir de mí escribir este comentario) tiene una firma de método de interfaz ligeramente diferente, now => 'void AddParameters (comando IDbCommand, SqlMapper.Identity identity)' –

1
  • Dapper.EntityFramework 1.26 tiene soporte para DbGeography
  • Dapper 1.32 tiene soporte incorporado para SqlGeography
  • Dapper 1.33 tiene soporte incorporado para SqlGeometry
  • Dapper.EntityFramework 1.33 tiene soporte incorporado para DbGeometry
  • Dapper 1.34 tiene soporte incorporado para SqlHierarchyId

Así que con las últimas bibliotecas; simplemente debería funcionar.