sql server 2008 - Usando Dapper con SQL Spatial Types como parámetro
sql-server-2008 orm (3)
Tengo un sistema que básicamente tiene que hacer una consulta como esta:
SELECT * FROM MyTable WHERE @parameter.STIntersects(MyGeometryColumn)
Esto es bastante simple de hacer al usar parámetros de SQL vainilla, solo tiene que crear su parámetro de una manera no típica (donde la variable del constructor es un SqlGeometryBuilder que yo uso para crear un rectángulo):
command.Parameters.Add(new SqlParameter
{
UdtTypeName = "geometry",
Value = builder.ConstructedGeometry,
ParameterName = "@paremeter"
});
Ahora, cuando trato de hacer esto usando dapper, me da 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 el 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.
La clave para implementar parámetros específicos de DB raros y maravillosos se reduce a SqlMapper.IDynamicParameters
Esta interfaz simple tiene un solo punto final:
public interface IDynamicParameters
{
void AddParameters(IDbCommand command);
}
Dapper ya tiene una implementación genérica de DB de esta interfaz llamada: DynamicParameters
que le permite manejar los valores de salida y retorno.
Para emular estas cosas espaciales, probaría 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 implementación simple de la interfaz maneja solo un único parámetro, pero se puede extender fácilmente para manejar múltiples params, ya sea al pasar desde el constructor o al agregar un método auxiliar AddParameter.
Si no te importa modificar Dapper en su núcleo, entonces puedes usar lo que he hecho ... https://gist.github.com/brendanmckenzie/4961483
Modifiqué Dapper para que aceptara Microsoft.SqlServer.Types.SqlGeography
parámetros de Microsoft.SqlServer.Types.SqlGeography
.
- 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
Entonces con las últimas bibliotecas; simplemente debería funcionar.