RuntimeBinderInternalCompilerException quando si utilizza Microsoft.SqlServer.Types con Dapper

.net dapper sql-server

Domanda

Utilizzo di un progetto Sql Server Data Tools la cui piattaforma di destinazione è impostata su uno di:

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

E distribuire a (localdb) \ Projects o (localdb) \ ProjectsV12

Chiamando una stored procedure che restituisce un tipo Geometry, Geography o HierachyId come:

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

Il seguente codice di chiamata:

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

risultati nella seguente eccezione sulla linea STEquals.

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException non gestito dal codice utente HResult = -2146233088 Messaggio = Si è verificata un'eccezione imprevista durante il binding di un'operazione dinamica
Origine = Microsoft.CSharp StackTrace: in Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind (carico utile 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 parametri, LabelTarget returnLabel) su System.Runtime.CompilerServices.CallSiteBinder.BindCore [T] (CallSite`1 site, Object [] args) su System.Dynamic.UpdateDelegates.UpdateAndExecute1 [T0, TRet] (sito CallSite, T0 arg0) su DATailor.Examp les.Dapper.SqlClient.Test.AllTypesDAOTest.TestAllTypesDynamic ()

Risposta accettata

Sebbene la causa principale non sia Dapper, esiste un'eccezione sottostante che viene ingerita.

Usando il codice ADO.Net come:

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

La seguente eccezione è lanciata a reader.GetValue

System.InvalidCastException non gestito HResult = -2147467262
Messaggio = [A] Impossibile eseguire il cast di Microsoft.SqlServer.Types.SqlGeometry su [B] Microsoft.SqlServer.Types.SqlGeometry. Il tipo A deriva da "Microsoft.SqlServer.Types, Version = 10.0.0.0, Culture = neutral, PublicKeyToken = 89845dcd8080cc91" nel contesto "Predefinito" nella posizione "C: \ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 10.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll'. Il tipo B ha origine da "Microsoft.SqlServer.Types, Versione = 11.0.0.0, Cultura = neutrale, PublicKeyToken = 89845dcd8080cc91" nel contesto "Predefinito" nella posizione "C: \ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 11.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll'. Source = DynamicGeometryIssue StackTrace: at DynamicGeometryIssue.TestDaoTestGeometry () in c: \ Users \ rich \ Documents \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ TestDao.cs: riga 27 su DynamicGeometryIssue.Program.Main (String [] args ) in c: \ Users \ rich \ Documenti \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ Program.cs: riga 15 in System.AppDomain._nExecuteAssembly (assembly RuntimeAssembly, String [] args) in System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) in Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () in System.Threading.ThreadHelper.ThreadStart_Context (stato dell'oggetto) in System.Threading.ExecutionContext.RunInternal (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) su System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) su System.Threading.Execu tionContext.Run (ExecutionContext executionContext, ContextCallback callback, Object state) in System.Threading.ThreadHelper.ThreadStart () InnerException:

La causa dell'eccezione di base è una nota violazione della modifica in SQL Server 2012. Vedere la sezione Tipi di dati CLR SQL della seguente documentazione MSDN

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

La risoluzione, che ha funzionato per me, è creare il seguente bindingRedirect in 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>

In alternativa, con .NET 4.5 è possibile modificare la stringa di connessione per includere un valore di "SQL Server 2012" per l'attributo "Versione di sistema tipo" per forzare SqlClient a caricare la versione 11.0 dell'assieme.

Un'altra soluzione è il codice come:

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

Tuttavia, non credo che questa sia un'opzione con Dapper.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow