2012-08-23 15 views
8

Mam element "Punkt", który zawiera współrzędne Id, Tekst i geografię.Mapowanie SqlGeography z Dapperem

CREATE TABLE [Point] (
    [Id] INT IDENTITY CONSTRAINT [PK_Point_Id] PRIMARY KEY, 
    [Coords] GEOGRAPHY NOT NULL, 
    [Text] NVARCHAR(32) NOT NULL, 
    [CreationDate] DATETIME NOT NULL, 
    [IsDeleted] BIT NOT NULL DEFAULT(0) 
) 

CREATE PROCEDURE [InsertPoint] 
    @text NVARCHAR(MAX), 
    @coords GEOGRAPHY 
AS BEGIN 
    INSERT INTO [Point](Text, Coords, CreationDate) 
    VALUES(@text, @coords, GETUTCDATE())  
    SELECT * FROM [Point] WHERE [Id] = SCOPE_IDENTITY() 
END 

To jest kod skryptu sql sql i procedura składowana wstawiania. Mam klasę za korzystanie elegancki:

public class DapperRequester : IDisposable { 
    private readonly SqlConnection _connection; 
    private SqlTransaction _transaction; 

    public DapperRequester(string connectionString) { 
     _connection = new SqlConnection(connectionString); 
     _connection.Open(); 
    } 
    public void Dispose() { 
     _connection.Close(); 
    } 

    public void BeginTransaction() { 
     _transaction = _connection.BeginTransaction(); 
    } 
    public void CommitTransaction() { 
     _transaction.Commit(); 
    } 
    public void RollbackTransaction() { 
     _transaction.Rollback(); 
    } 

    public void Query(string query, object parameters = null) { 
     Dapper.SqlMapper.Execute(_connection, query, parameters, transaction: _transaction); 
    } 

    public void QueryProc(string procName, object parameters = null) { 
     Dapper.SqlMapper.Execute(_connection, procName, parameters, commandType: CommandType.StoredProcedure, transaction: _transaction); 
    } 

    public IEnumerable<T> Execute<T>(string query, object parameters = null) { 
     return Dapper.SqlMapper.Query<T>(_connection, query, parameters, transaction: _transaction); 
    } 

    public IEnumerable<dynamic> ExecuteProc(string procName, object parameters = null) { 
     return Dapper.SqlMapper.Query(_connection, procName, parameters, 
             commandType: CommandType.StoredProcedure, transaction: _transaction); 
    } 

    public IEnumerable<T> ExecuteProc<T>(string procName, object parameters = null) { 
     return Dapper.SqlMapper.Query<T>(_connection, procName, parameters, 
             commandType: CommandType.StoredProcedure, transaction: _transaction); 
    } 
} 

C# -class jest:

public class Point 
{ 
    public int Id { get; set; } 
    public SqlGeography Coords { get; set; } 
    public string Text { get; set; } 
} 

i repozytorium ma metodę

public Point InsertPoint(string text, SqlGeography coords) 
    { 
     using (var requester = GetRequester()) 
     { 
      return requester.ExecuteProc<Point>("InsertPoint", new { text, coords }).FirstOrDefault(); 
     } 
    } 

Kiedy używać takiego systemu dla każdej innej klasy, wszystko jest okey , ale jest problem z mapowaniem, myślę, że jest to spowodowane typem SqlGeography. Używanie:

SqlGeography coords = new SqlGeography(); 
     coords = SqlGeography.Point(10.5, 15.5, 4326); 
     Point point = new Point { Coords = coords, Text = "Text" }; 
     point = Repositories.PointRepository.InsertPoint(point.Text, point.Coords); 

Mam wyjątek The member coords of type Microsoft.SqlServer.Types.SqlGeography cannot be used as a parameter value

Czy jest jakiś sekret mapowania tego typu?

Odpowiedz

9

Dapper 1.32 teraz includes direct support for this. Twój kod powinien teraz po prostu zadziałać.

+0

Czy ma również współpracować z QueryMultiple? Otrzymuję komunikat "Błąd parsowania kolumna 5" podczas odczytu.Read. A kolumna 5 to wielokąt SqlGeography. –

+1

Należy używać właściwej wersji SqlGeography w zależności od używanej wersji bazy danych MS. Musiałem zainstalować SqlGeography w wersji 10.5 dla Sql 2012. Potem działało dobrze z Dapper. – mac10688

1

Dapper nie obsługuje określonych typów dostawców DB. W twoim przypadku GEOGRAFIA.

Wytworny ma DB szczegóły konkretnej implementacji, to działa na wszystkich .net ado zawierająca SQLite SQLCE, firebird, Oracle, MySQL i SQL Server

Aby obsłużyć to z param Dapper, musiałbyś napisać dla niego swoją własną obsługę. Na przykład patrz: answer.

Powodzenia

1

Wpadłem na podobny problem. Odkryłem, że Dapper odwzoruje pola wynikowe na Microsoft.SqlServer.Types.SqlGeography, ale używanie ich jako parametrów nie działa.

Zmodyfikowałem plik SqlMapper.cs, aby uwzględnić obsługę tego typu. Możesz zobaczyć Gist tutaj: https://gist.github.com/bmckenzie/4961483

Kliknij na "Wersje", aby zobaczyć, co zmieniłem.