Quantcast
Channel: Entwicklung – HanseVision Blog
Viewing all articles
Browse latest Browse all 46

Aus der Praxis – SQL Server Typ geography in Entity Framework und Co.

$
0
0

In meinem letzten Artikel habe ich den Datentyp geography vorgestellt, den es seit Microsoft SQL Server 2008 für Geodaten gibt. Nun besteht die Welt ja nicht nur aus SQL Server, oft wird ein objektrelationaler Mapper (OR Mapper) genutzt um aus dem Programmcode auf die Datenbank zuzugreifen.

Hier ergibt sich ein Problem, denn z.B. Entity Framework unterstützt den geography Datentyp noch nicht. Das wird es erst ab der Version 5.0, die aktuell noch im Beta-Stadium ist. Hier bedarf es eines Workarounds, den ich hier für die Nutzung von einfachen Punkten zeigen möchte:

public struct GeographyPoint
{
    private static Regex findDecimalNumbers = new Regex(@”[0-9\.]+”, RegexOptions.Compiled);

    public double Latitude;
    public double Longitude;

    public GeographyPoint(double latitude, double longitude)
    {
        this.Latitude = latitude;
        this.Longitude = longitude;
    }

    public override string ToString()
    {
        return string.Concat(“POINT(“, Longitude.ToString(CultureInfo.InvariantCulture), ” “, Latitude.ToString(CultureInfo.InvariantCulture), “)”);
    }

    public static GeographyPoint Parse(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
        else
        {
            MatchCollection matches = findDecimalNumbers.Matches(s);
            if (matches.Count == 2)
            {
                return new GeographyPoint(double.Parse(matches[1].Value, CultureInfo.InvariantCulture), double.Parse(matches[0].Value, CultureInfo.InvariantCulture));
            }
            else
            {
                throw new FormatException();
            }
        }
    }
}

Diese Klasse repräsentiert einen einzelnen Punkt mit den Koordinaten Latitude und Logitude und bietet Methoden um diesen Punkt in einen von SQL Server lesbaren String und wieder zurück umzuwandeln. In einer Datenklasse, kann er nun wie folgt eingesetzt werden:

public class Address
{
    public string StreetName { get; set; }
    public string StreetNumber { get; set; }

    public GeographyPoint Coordinates { get; set; }

    public string CoordinatesString
    {
        get
        {
            return Coordinates.ToString();
        }
        set
        {
            Coordinates = GeographyPoint.Parse(value);
        }
    }
}

Im Programmcode kann nun das Property Coordinates genutzt werden, der OR Mapper verwendet aber stattdessen CoordinatesString. Zum lesen und schreiben werden Stored Procedures genutzt, die dann folgende Zeilen beinhalten:

SELECT StreetName, StreetNumber, Coordinates.ToString() AS CoordinatesString FROM T_Geodata

und

INSERT INTO T_Geodata (StreetName, StreetNumber, Coordinates)

    VALUES (@StreetName, @StreetNumber, geography::STGeomFromText (@CoordinatesString, 4326))

Eine alternative Version wäre die Übermittlung als zwei Fließkommazahlen (@Latitude und @Longitude) und das Speichern mittels der Funktion geography::Point([@Latitude], [@Longitude], 4326).


Viewing all articles
Browse latest Browse all 46