2012-08-23 22 views
8

Tengo la entidad "Point", que contiene Id, texto y coordenadas geográficas.Asignación de SqlGeography con Dapper

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 

Este es el código ts sql de la tabla y el procedimiento almacenado de inserción. Tengo clase para el uso pulcro:

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 es:

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

Y repositorio tiene método

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

Cuando uso de estos sistemas para cualquier otra clase, todo está okey , pero hay un problema con el mapeo, creo que es por el tipo de SqlGeography .. Utilizando:

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

Y tengo una excepción The member coords of type Microsoft.SqlServer.Types.SqlGeography cannot be used as a parameter value

¿Hay algún secreto de mapeo de ese tipo?

Respuesta

9

Dapper 1.32 ahora includes direct support for this. Su código debería ahora simplemente trabajar.

+0

¿Se supone que también funciona con QueryMultiple? Obtengo "Error al analizar la columna 5" al leer el lector. Leer. Y la columna 5 es un polígono de SqlGeography. –

+1

Tenga cuidado de usar la versión correcta de SqlGeography dependiendo de la versión de la base de datos ms que esté utilizando. Tuve que instalar SqlGeography Versión 10.5 para Sql 2012. Luego funcionó bien con Dapper. – mac10688

1

Dapper no es compatible con los tipos de datos específicos de DB Provider. En tu caso es GEOGRAFÍA.

Dapper no tiene detalles específicos de la implementación de base de datos, funciona a través de todos .net preámbulos proveedores incluyendo sqlite, SQLCE, pájaro de fuego, Oracle, MySQL y SQL Server

Con el fin de manejar este parámetro con Dapper, tendrías que escribir tu propio manejo para eso. Para un ejemplo, vea esto answer.

Buena suerte

1

Me encontré con un problema similar. Descubrí que Dapper asignaría los campos resultantes al Microsoft.SqlServer.Types.SqlGeography, pero usarlos como parámetros no funcionó.

He modificado el archivo SqlMapper.cs para incluir compatibilidad con este tipo. Puede ver el Gist aquí: https://gist.github.com/bmckenzie/4961483

Haga clic en "Revisiones" para ver lo que he cambiado.