Utilisation de Dapper avec des types spatiaux SQL en tant que paramètre

dapper orm spatial sql-server-2008

Question

J'ai un système qui doit essentiellement faire une requête comme celle-ci:

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

Ceci est assez simple à faire lors de l'utilisation de paramètres SQL à la vanille, il vous suffit de créer votre paramètre d'une manière non typique (où la variable constructeur est un SqlGeometryBuilder que j'utilise pour créer un rectangle):

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

Maintenant, quand j'essaie de faire ceci en utilisant dapper, j'ai une erreur qu'il ne peut pas comprendre comment l'utiliser comme paramètre. Quelqu'un qui a ce travail, ou des conseils sur la façon d'activer cela? J'ai une solution de contournement, mais cela implique d'utiliser la représentation sous forme de chaîne et de la convertir en un type de géométrie dans ma requête SQL. Je ne veux vraiment pas ça.

Pour répondre au commentaire, l'erreur que j'obtiens est "Le paramètre membre de type Microsoft.SqlServer.Types.SqlGeometry ne peut pas être utilisé comme valeur de paramètre". En d'autres termes, dapper ne sait pas comment traiter un objet SqlGeometry en tant que paramètre.

Réponse acceptée

La clé de l'implémentation de paramètres spécifiques à la base de données étranges et merveilleux se résume à SqlMapper.IDynamicParameters

Cette interface simple possède un seul point de terminaison:

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

Dapper a déjà une implémentation générique de base de données de cette interface appelée: DynamicParameters qui vous permet de gérer les valeurs de sortie et de retour.

Pour imiter ce genre de choses spatiales, je voudrais essayer quelque chose comme:

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

Usage:

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

Cette implémentation simple de l'interface ne gère qu'un seul paramètre, mais elle peut facilement être étendue pour gérer plusieurs paramètres, soit en passant du constructeur, soit en ajoutant une méthode AddParameter.


Réponse d'expert

  • Dapper.EntityFramework 1.26 prend en charge DbGeography
  • Dapper 1.32 a un support intégré pour SqlGeography
  • Dapper 1.33 a un support intégré pour SqlGeometry
  • Dapper.EntityFramework 1.33 a un support intégré pour DbGeometry
  • Dapper 1.34 prend en charge SqlHierarchyId

Donc, avec les dernières bibliothèques; cela devrait simplement fonctionner.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi