RuntimeBinderInternalCompilerException al usar Microsoft.SqlServer.Types con Dapper

.net dapper sql-server

Pregunta

Utilizando un proyecto de Herramientas de Datos de Servidor Sql cuya plataforma de destino está configurada en uno de:

  • SQL Server 2008
  • SQL Server 2012
  • SQL Server 2014

E implementando en (localdb) \ Projects o (localdb) \ ProjectsV12

Llamar a un procedimiento almacenado que devuelve un tipo de Geometría, Geografía o HierachyId como, por ejemplo:

CREATE PROCEDURE [dbo].[SelectSqlGeometry]
    @x Geometry
AS
    SELECT @x as y
RETURN 0

El siguiente código de llamada:

var result = Connection.Query("dbo.SelectSqlGeometry", new { x = geometry }, commandType: CommandType.StoredProcedure).First();
bool isSame = ((bool)geometry.STEquals(result.y));

da como resultado la siguiente excepción en la línea STEquals.

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException no fue controlada por el código de usuario HResult = -2146233088 Mensaje = Ocurrió una excepción inesperada al vincular una operación dinámica
Fuente = Microsoft.CSharp StackTrace: en Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind (carga útil DynamicMetaObjectBinder, 1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding) at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable IEnumerable 1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding) at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable 1 args, IEnumerable 1 arginfos, DynamicMetaObject onBindingError) at Microsoft.CSharp.RuntimeBinder.CSharpConvertBinder.FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion) at System.Dynamic.DynamicMetaObject.BindConvert(ConvertBinder binder) at System.Dynamic.ConvertBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args) at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection 1 parámetros, LabelTarget returnLabel) en System.Runtime.CompilerServices.CallSiteBinder.BindCore [T] (CallSite`1 site, Object [] args) en System.Dynamic.UpdateDelegates.UpdateAndExecute1 [T0, TRet] (sitio de CallSite, T0 arg0) en DATailor.Examp les.Dapper.SqlClient.Test.AllTypesDAOTest.TestAllTypesDynamic ()

Respuesta aceptada

Aunque la causa raíz no es Dapper, hay una excepción subyacente que se está tragando.

Usando el código ADO.Net como:

var geometry = Util.CreateSqlGeometry();
SqlDataReader reader=null;
SqlCommand cmd=null;
try
{
    cmd = new SqlCommand("dbo.SelectSqlGeometry", (SqlConnection)Connection);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new SqlParameter("@x", geometry) { UdtTypeName = "Geometry" });
    cmd.ExecuteNonQuery();
    reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        var y = (SqlGeometry)reader.GetValue(0);
        var same = geometry.STEquals(y);
    }
    reader.Dispose();
    reader = null;
}
finally
{
    if (reader != null)
    {
        if (!reader.IsClosed) try { cmd.Cancel(); }
            catch {}
        reader.Dispose();
    }
    if (cmd != null) cmd.Dispose();
    Connection.Close();
}

Se lanza la siguiente excepción al reader.GetValue

System.InvalidCastException no fue manejado HResult = -2147467262
Message = [A] Microsoft.SqlServer.Types.SqlGeometry no se puede convertir a [B] Microsoft.SqlServer.Types.SqlGeometry. El tipo A se origina de 'Microsoft.SqlServer.Types, Version = 10.0.0.0, Culture = neutral, PublicKeyToken = 89845dcd8080cc91' en el contexto 'Default' en la ubicación 'C: \ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 10.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll '. El tipo B se origina de 'Microsoft.SqlServer.Types, Version = 11.0.0.0, Culture = neutral, PublicKeyToken = 89845dcd8080cc91' en el contexto 'Default' en la ubicación 'C: \ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 11.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll '. Fuente = DynamicGeometryIssue StackTrace: en DynamicGeometryIssue.TestDao.TestGeometry () en c: \ Users \ rich \ Documents \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ TestDao.cs: línea 27 en DynamicGeometryIssue.Program.Main (String [] args ) en c: \ Users \ rich \ Documents \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ Program.cs: línea 15 en System.AppDomain._nExecuteAssembly (ensamblado RuntimeAssembly, String [] args) en System.AppDomain.ExecuteAssembly (String) assemblyFile, Evidence assemblySecurity, String [] args) en Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () en System.Threading.ThreadHelper.ThreadStart_Context (Estado del objeto) en System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) en System.Threading.ExecutionContext.Run (ExecutionContext executionContext, Callback de ContextCallback, estado Object, Boolean preserveSyncCtx) en System.Threading.Execu tionContext.Run (ExecutionContext executionContext, devolución de llamada ContextCallback, estado del objeto) en System.Threading.ThreadHelper.ThreadStart () InnerException:

La causa de la excepción subyacente es un cambio disruptivo conocido en SQL Server 2012. Consulte la sección Tipos de datos CLR de SQL de la siguiente documentación de MSDN

http://msdn.microsoft.com/en-us/library/ms143179(v=sql.110).aspx

La resolución que me ha funcionado es crear el siguiente bindingRedirect en app.config o web.config.

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.SqlServer.Types"
                      publicKeyToken="89845dcd8080cc91"
                      culture="neutral" />
    <bindingRedirect oldVersion="10.0.0.0"
                     newVersion="11.0.0.0"/>
  </dependentAssembly>
</assemblyBinding>
</runtime>

Alternativamente, con .NET 4.5 puede cambiar su cadena de conexión para incluir un valor de "SQL Server 2012" para el atributo "Tipo de versión del sistema" para forzar a SqlClient a cargar la versión 11.0 del ensamblado.

Otra solución es un código como:

var geo = SqlGeography.Deserialize(rdr.GetSqlBytes(0));

Sin embargo, no creo que esta sea una opción con Dapper.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué