【问题标题】:Can a .NET 4.5.2 Assembly be programmed to use CLR version 2.0 for SQL Server 2008 R2可以对 .NET 4.5.2 程序集进行编程以将 CLR 2.0 版用于 SQL Server 2008 R2
【发布时间】:2023-03-06 03:37:01
【问题描述】:

我正在 Microsoft .NET Framework 4.5.2 中编写一个程序集,该程序集定义了要在数据库连接两端(在数据库内部以及 .NET 端的 DataTable)上使用的类型。

服务器正在运行 SQL Server 2008 R2。

SQL Server CLR 版本是 v2.0.50727,windows server 上的 .NET 版本(2008 R2 也是)是 4.5.2。

由于 CLR 版本,SQL Server 实例将仅支持 .NET 3.5 及更低版本。如果不立即升级到 SQL Server 2012,我无法更改它,因为这是一个生产服务器,但我已经围绕 ASP.Net 4.5.2 构建了一个应用程序,我不相信我现在可以将其更改为使用 3.5。我对这些类型的经验是,它们在数据连接的两端必须相同。

我要么必须将 4.5.2 类型的 .dll 强制限制为 CLR v2,强制编译器允许混合版本的 .NET 程序集,要么找到另一种方法绕过 SQL Server 2008 R2 上的 CLR v2 限制。

在我正在使用的时间范围内无法升级 SQL Server 实例。

有没有人能解决这个问题?

更新:

作为解决方案的一部分,我在类型类定义中实现了 IBinarySerialize 和 Serialize 接口。我在 ToString() 和 Parse 方法中使用 XDocument。

在 .NET 方面,我使用存储过程调用和 Dapper ORM 来执行 CRUD 操作。自定义类型必须使用 ToString() 方法发送到 SQL Server 实例,并且在使用 SQL Server 的 Write 实现存储之前,该类型由 SQL Server 使用 Parse 方法解析。

使用 Read 方法从记录中获取数据并使用 ToString() 方法发送到 .NET 端。在 .NET 端,返回值随后通过 .NET 接口使用反射存储在使用 Parse 方法的类型中。

反射接口要求 .NET 类型与 SQL Server 程序集类型匹配。发送到 .NET 反射接口的信息包括有关创建被发送到 .NET 端的信息的类型程序集的信息。

我想底线是我需要一种方法来欺骗反射接口,使其相信使用 .NET 3.5 创建的类型与以相同方式声明的 .NET 4.5.2 类型相同。

【问题讨论】:

    标签: sql-server sql-server-2008-r2 sqlclr asp.net-4.5


    【解决方案1】:

    鉴于无法绕过 SQL Server 2005、2008 和 2008 R2 的 CLR 2.0 限制,您可能无法在两边都使用 完全相同 类型。我从来没有尝试过混合版本的 DLL,但不知道这会给你带来什么,除非你有不同的代码用于 CLR 2.0 用法,因为不会有任何“CLR 4.0 或更高版本中的新”功能可用于程序集运行在 SQL Server 2008 R2 中,在这种情况下,您不妨编写程序集以在 CLR 2.0 中工作,因为由于向后兼容性,它在 CLR 4.0 中也能正常运行。

    您可能会考虑保存可用于任一版本的类型的序列化表示,并将其保存为 SQL Server 端的 XMLVARBINARY,以便将列升级到将来升级 SQL Server 后的 UDT。但是,您始终可以在构造函数(或其他方法)中读取该序列化值中的 T-SQL 代码。基本上,它现在只需要在数据库方面多走一步。这有意义吗?

    【讨论】:

    • 我正在使用重写的 ToString() 函数和 Parse 函数以及 IBinarySerialize 实现来输入和存储数据。必须在 .NET 端使用 ToString() 函数将信息发送到 SQL Server,因为我还使用带有存储过程集的 Dapper 接口来执行 CRUD 操作。返回的 Datatable 发送有关程序集的信息并在另一端查找相同的程序集。我知道这一点是因为我在第一次尝试使用创建的程序集和类型时遇到了错误。
    【解决方案2】:

    我已确定问题是由 Dapper 微 ORM 引起的。 Dapper 处理与数据库通信的序列化和反序列化。

    SQL Server 发回指示它返回的表的每一列的类型的信息。这就是自定义类型使用特定程序集这一事实的来源。

    Dapper 使用此信息来加载自定义类型的程序集并使用反射解析类型以确定要使用的方法。如果您使用 Dapper 或其他 ORM,则类型必须在通信双方定义相同。我不能说使用实体框架是否会出现同样的问题,因为我没有使用它。我们的编程一直在为所有 .NET 程序使用 Dapper/Dapper Extensions。

    因此,问题的真正解决方案是使用通用的较低级别的 DataTable 方法,而不是在这种情况下使用 ORM。

    感谢 Solomon Rutzky 为我指明了正确的方向。

    更新:

    自从发布此解决方案以来,我尝试了一些我认为以前不会起作用的方法。

    我使用 .NET 3.5 而不是 .NET 4.5.2 简单地重新编译了程序集,并将它们重新安装在我用于开发和测试的 SQL Server 2012 实例上。编码细节没有变化。我没有使用 async/await,这是 3.5 和 4.x 之间的主要区别,所以这不是问题。

    这确实起到了作用。我不必重写用于与数据库通信的 Web Api 2.2 Web 服务来适应规避 Dapper。 Dapper 只查看程序集编号,我没有更改它。

    这可能不适用于每个程序集,但它适用于我的应用程序集的特定情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 2013-01-29
      相关资源
      最近更新 更多