我正在编写一个应用程序(使用本地安装的.NET Framework 4.5.2 SQL Server 2014).该应用程序需要支持SQL Server 2014和以前的版本.
使用内置的SQLCLR类型(SqlGeometry,SqlGeography,SqlHierarchyID)读取数据时,标准的ADO.NET方法(例如DataReader.GetValues())使用10.0.0.0程序集,并由于与加载的不匹配而抛出异常( v11或v12)版本.
在Breaking Changes in SQL Server 2012中记录了推理(尽管需要一段时间才能发现)(对于11.0.0.0程序集).对于SQL Server 2012,列出了三种解决方法:
>在SQLConnection.ConnectionString中使用类型系统版本= SQL Server 2012
> OR:使用app.config / runtime / assemblyBinding / dependentAssembly将v10.0.0.0重新映射到v11.0.0.0
> OR(不是一种非常“整洁”的方式来处理它):重写自己的代码以从SqlBytes实例手动反序列化…
从安装了SQL Server 2014的计算机进行开发时,程序集版本为v12.0.0.0,并出现类似问题:
System.InvalidCastException: Unable to cast object of type
Microsoft.SqlServer.Types.SqlGeometry
to typeMicrosoft.SqlServer.Types.SqlGeometry
.
对于SQL Server 2014(除了可怕的手动反序列化方法),似乎只有一种解决方法(在破坏性更改中未正式记录) – 似乎v4.5 SqlConnection还没有赶上版本的SQL Server:
>使用app.config / runtime / assemblyBinding / dependentAssembly将v10.0.0.0重新映射到v12.0.0.0
问题:除了在app.config中重新映射v10.0.0.0到v12.0.0.0(这似乎有效)之外,是否还有其他(更简单)方法将使用引用的汇编版本?
下面的快速代码示例显示了失败(没有组装重新映射):
private static void DoStuff()
{
SqlGeography geog_val = SqlGeography.STGeomFromText(new SqlChars("POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))"), 4326);
SqlGeometry geom_val = SqlGeometry.Parse("LINESTRING(1 1,2 3,4 8, -6 3)");
prm_geog.Value = DBNull.Value; prm_geom.Value = geom_val; ReadReturnedSpatialColumns(cmd);
prm_geog.Value = geog_val; prm_geom.Value = DBNull.Value; ReadReturnedSpatialColumns(cmd);
}
private static void ReadReturnedSpatialColumns(SqlCommand cmd)
{
using (var dr = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
dr.Read(); var items = new object[2]; dr.GetValues(items);
var geog_test = dr.IsDBNull(0) ? SqlGeography.Null : (SqlGeography)items[0];
var geom_test = dr.IsDBNull(1) ? SqlGeometry.Null : (SqlGeometry)items[1];
}
}
最佳答案 Framework 4.6.1仍然存在此问题,除了您已经发现的3之外,似乎没有其他解决方法.所以对你的问题的简短回答是否定的.
但是我会质疑你是否真的需要版本12的空间类型,因为(据我所知)他们不会在v11类型上添加任何东西.如果您更喜欢使用v11类型,以便可以使用Type System Version = SQL Server 2012解决方法,则可以安装包含所有三个版本(10,11,12)的Nuget package – 它专门设计为允许您部署到可能未安装MSSQL的服务器.
作为奖励,直接引用该包并使用Type System Version = SQL Server 2012将确保您的应用程序将始终使用2012年空间类型,因此如果它决定返回不同版本的版本,升级到SQL 2016将不会破坏任何内容它们(例如13或14,或者2016年将使用的任何东西)默认情况下.