將Microsoft.SqlServer.Types與Dapper一起使用時的RuntimeBinderInternalCompilerException

.net dapper sql-server

使用其目標平台設置為以下之一的Sql Server Data Tools項目:

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

並部署到(localdb)\ Projects或(localdb)\ ProjectsV12

調用返回Geometry,Geography或HierachyId類型的存儲過程,例如:

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

以下調用代碼:

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

在STEquals系列中導致以下異常。

Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException未被用戶代碼處理HResult = -2146233088消息=綁定動態操作時發生意外異常
Source = Microsoft.CSharp StackTrace:在Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind上的Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder有效內容,IEnumerable 1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding) at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, 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 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在System.Runtime.CompilerServices.CallSiteBinder.BindCore [T]的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參數,LabelTarget returnLabel)中的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 (CallSite`1 site,Object [] args)在DATailor.Examp的System.Dynamic.UpdateDelegates.UpdateAndExecute1 [T0,TRet](CallSite站點,T0 arg0) les.Dapper.SqlClient.Test.AllTypesDAOTest.TestAllTypesDynamic()

一般承認的答案

雖然根本原因不是Dapper,但是有一個潛在的異常被吞噬。

使用ADO.Net代碼,如:

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

reader.GetValue拋出以下異常

System.InvalidCastException未處理HResult = -2147467262
消息= [A] Microsoft.SqlServer.Types.SqlGeometry無法強制轉換為[B] Microsoft.SqlServer.Types.SqlGeometry。類型A源自'Microsoft.SqlServer.Types,Version = 10.0.0.0,Culture = neutral,PublicKeyToken = 89845dcd8080cc91',位於'默認'位置'C:\ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 10.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll“。類型B源自'Microsoft.SqlServer.Types,Version = 11.0.0.0,Culture = neutral,PublicKeyToken = 89845dcd8080cc91',位於'默認'位置'C:\ Windows \ assembly \ GAC_MSIL \ Microsoft.SqlServer.Types \ 11.0 .0.0__89845dcd8080cc91 \ Microsoft.SqlServer.Types.dll“。 Source = DynamicGeometryIssue StackTrace:at DynamicGeometryIssue.TestDao.TestGeometry()in c:\ Users \ rich \ Documents \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ TestDao.cs:第27行,位於DynamicGeometryIssue.Program.Main(String [] args )在System.AppDomain.ExecuteAssembly(String)中的System.AppDomain._nExecuteAssembly(RuntimeAssembly程序集,String [] args)中的c:\ Users \ rich \ Documents \ Visual Studio 2013 \ Projects \ DynamicGeometryIssue \ DynamicGeometryIssue \ Program.cs:第15行在System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object)中的System.Threading.ThreadHelper.ThreadStart_Context(Object state)上的Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()中的assemblyFile,Evidence assemblySecurity,String [] args) System.Threading.Execu上的System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)中的state,Boolean preserveSyncCtx) System.Threading.ThreadHelper.ThreadStart()InnerException中的tionContext.Run(ExecutionContext executionContext,ContextCallback回調,Object狀態):

基礎異常的原因是SQL Server 2012中已知的重大更改。請參閱以下MSDN文檔的SQL CLR數據類型部分

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

對我有用的解決方案是在app.config或web.config中創建以下bindingRedirect。

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

或者,使用.NET 4.5,您可以更改連接字符串以包含“Type System Version”屬性的值“SQL Server 2012”,以強制SqlClient加載程序集的11.0版。

另一種解決方法是代碼:

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

但是,我不相信這是Dapper的選擇。



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow