Ich habe ein System, das im Grunde eine Abfrage wie folgt machen muss:
SELECT * FROM MyTable WHERE @parameter.STIntersects(MyGeometryColumn)
Dies ist ziemlich einfach zu tun, wenn Sie Vanilla-SQL-Parameter verwenden, Sie müssen nur Ihren Parameter in einer nicht-typischen Weise erstellen (wobei die Builder-Variable ein SqlGeometryBuilder ist, mit dem ich ein Rechteck erstelle):
command.Parameters.Add(new SqlParameter
{
UdtTypeName = "geometry",
Value = builder.ConstructedGeometry,
ParameterName = "@paremeter"
});
Nun, wenn ich dies mit Dapper versuche, bekomme ich einen Fehler, dass es nicht herausfinden kann, wie man das als Parameter benutzt. Wer hat das funktioniert, oder irgendwelche Hinweise, wie man das ermöglicht? Ich habe eine Problemumgehung, aber das beinhaltet die Verwendung der Zeichenfolgendarstellung und das Konvertieren in einen Geometrietyp in meiner SQL-Abfrage. Ich will das wirklich nicht.
Um den Kommentar zu beantworten, ist der Fehler, den ich bekomme, 'der Member-Parameter vom Typ Microsoft.SqlServer.Types.SqlGeometry kann nicht als Parameterwert verwendet werden'. Mit anderen Worten, Dapper kann nicht mit einem SqlGeometry-Objekt als Parameter umgehen.
Der Schlüssel zum Implementieren von seltsamen und wunderbaren DB-spezifischen Parametern läuft auf SqlMapper.IDynamicParameters
Diese einfache Schnittstelle hat einen einzigen Endpunkt:
public interface IDynamicParameters
{
void AddParameters(IDbCommand command);
}
Dapper hat bereits eine generische DB-Implementierung dieser Schnittstelle namens DynamicParameters
, mit der Sie Ausgabe- und Rückgabewerte verarbeiten können.
Um dieses räumliche Zeug nachzuahmen, würde ich versuchen, etwas wie:
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
});
}
}
Verwendung:
cnn.Query("SELECT * FROM MyTable WHERE @parameter.STIntersects(MyGeometryColumn)",
new SpatialParam("@parameter", builder.ConstructedGeometry));
Diese einfache Implementierung der Schnittstelle handhabt nur einen einzigen Parameter, aber sie kann leicht erweitert werden, um mehrere Parameter zu behandeln, entweder durch Übergabe vom Konstruktor oder durch Hinzufügen einer Hilfs-AddParameter-Methode.
DbGeography
SqlGeography
SqlGeometry
DbGeometry
SqlHierarchyId
Also mit den neuesten Bibliotheken; es sollte einfach funktionieren.