在 SQL CLR 中使用 Entity Framework 6 / EF Core
Using Entity Framework 6 / EF Core inside SQL CLR
Microsoft Azure 技术支持已确认在SQL 服务器托管实例 CLR 中 支持所有版本的 .Net 4.XX,包括 4.7.2。
我们正在运行使用 4.7.2 和最新的 EF 6.2 构建业务层的某些部分
https://patrickdesjardins.com/blog/how-to-use-third-party-dll-reference-in-a-sql-clr-function
因此,为了利用对经过良好测试的代码的现有投资,我们希望将某些业务层移至数据库中。
但是我们运行在发布的时候遇到了问题。
Creating [System.Dynamic]...
Warning: The Microsoft .NET Framework assembly 'system.dynamic,
version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.'
您正在注册的内容在 SQL 服务器托管环境中未经过全面测试,因此不受支持。将来,如果升级或维护此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。请参阅 SQL 服务器联机丛书以了解更多详细信息。
(47,1):SQL72014:.Net SqlClient 数据提供程序:
消息 6218,级别 16,状态 2,第 1 行
为程序集 'System.Dynamic' 创建程序集失败,因为程序集 'System.Dynamic' 验证失败。 检查引用的程序集是否是最新的和可信的(对于 external_access或不安全)在数据库中执行。
CLR 验证程序错误消息(如果有)将跟随此消息 [ :
System.Dynamic.ArgBuilder::MarshalToRef][mdToken=0x6000002][偏移量
0x00000000] 代码大小为零。 [:
System.Dynamic.ArgBuilder::UnmarshalFromRef][mdToken=0x6000003][偏移量
P.S。 (恕我直言,EF 核心是否也无所谓,尽管我们正在使用 EF6.2 尝试此操作)
编辑:
已对我所指的所有程序集授予 UNSAFE 权限:
以下是所有依赖项:
<ItemGroup>
<Reference Include="Microsoft.CSharp">
<HintPath>..\packages2019\dotnet 4.7.2\Microsoft.CSharp.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Dynamic">
<HintPath>..\packages2019\dotnet 4.7.2\System.Dynamic.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Runtime.Serialization">
<HintPath>..\packages2019\dotnet 4.7.2\System.Runtime.Serialization.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="SMDiagnostics">
<HintPath>..\packages2019\v4.0.30319\SMDiagnostics.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.ServiceModel.Internals">
<HintPath>..\packages2019\v4.0.30319\System.ServiceModel.Internals.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<SpecificVersion>True</SpecificVersion>
<IsModelAware>True</IsModelAware>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<SpecificVersion>True</SpecificVersion>
<IsModelAware>True</IsModelAware>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
</Reference>
编辑 3:Azure 中的不安全代码 SQL 服务器 MI
编辑 4:
- 表演终结者是:
System.RunTime.Serialization
、
CREATE ASSEMBLY [System.Runtime.Serialization]
AUTHORIZATION [dbo]
FROM 0x4D5...
WITH PERMISSION_SET = UNSAFE;
这阻止我在数据库中创建 Entity Framework 不安全程序集。我们可以通过 system.Runtime.Serialization 吗?
GO
CREATE ASSEMBLY [EntityFramework]
AUTHORIZATION [dbo]
FROM 0x4D5A90...
WITH PERMISSION_SET = UNSAFE;
GO
PRINT N'Creating [EntityFramework.SqlServer]...';
GO
CREATE ASSEMBLY [EntityFramework.SqlServer]
AUTHORIZATION [dbo]
FROM 0x4...
WITH PERMISSION_SET = UNSAFE;
Warning: The Microsoft .NET Framework assembly
'system.runtime.serialization, version=4.0.0.0, culture=neutral,
publickeytoken=b77a5c561934e089.' you are registering is not fully
tested in the SQL Server hosted environment and is not supported. In
the future, if you upgrade or service this assembly or the .NET
Framework, your CLR integration routine may stop working. Please refer
SQL Server Books Online for more details. Msg 6218, Level 16, State 2,
Line 11 CREATE ASSEMBLY for assembly 'System.Runtime.Serialization'
failed because assembly 'System.Runtime.Serialization' failed
verification. Check if the referenced assemblies are up-to-date and
trusted (for external_access or unsafe) to execute in the database.
CLR Verifier error messages if any will follow this message [ :
System.AppContextDefaultValues::PopulateDefaultValues][mdToken=0x6000001]
[offset 0x00000000] Code size is zero.
SQL 服务器的 CLR 主机将使用系统上安装的最高版本的 .NET Framework,作为它链接到的 CLR 版本。 SQL Server 2005 - 2008 R2 链接到 CLR 2.0 版,因此它们将使用 .NET Framework 2.0、3.0 和 3.5 版。 SQL Server 2012 及更新版本都链接到 CLR 4.0 版,因此将使用 .NET Framework 版本 4.x.
也就是说,有些框架库是 built-in,不需要手动添加。这些列在这里:
Supported .NET Framework Libraries
如果您需要的库不在该列表中,您可以自己添加,但是这并不意味着您可以添加任何库。 SQL 服务器只允许纯 MSIL 库,不允许混合模式(混合 = 包含托管和非托管代码)。如果您需要一个混合模式的库,那么您无法将其加载到 SQL 服务器中。另外,请记住,即使今天的库是纯 MSIL,也不意味着它不能在未来的框架更新中转换为混合模式(是的,这已经发生了)。
考虑到所有这些,错误消息中的以下项目:
Code size is zero.
可能表示您正在尝试加载参考库。您需要加载 actual 库,而不是它的参考版本。
我在 SQL Server 2017 上尝试了以下操作,并且能够全部加载它们,但并非所有都需要显式加载。有些自动加载其他的,因为它们在同一个文件夹中:
CREATE ASSEMBLY [Microsoft.CSharp]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.CSharp.dll'
WITH PERMISSION_SET = UNSAFE;
-- includes System.Dynamic
CREATE ASSEMBLY [System.Runtime.Serialization]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE;
-- includes SMDiagnostics, System.ServiceModel.Internals
然后检查:
SELECT * FROM sys.assemblies;
/*
Microsoft.CSharp
System.Dynamic
System.Runtime.Serialization
System.ServiceModel.Internals
SMDiagnostics
*/
请注意,目前我将数据库设置为 TRUSTWORTHY ON
。这不是我通常推荐的东西,也可能不是必需的,但在我完成我的 post 处理如何正确地 和轻松地 、TRUSTWORTHY
之前就够了。
我没有要加载的 EntityFramework 库,但是您遇到的错误是第一个,而我在上面 post 编写的语句没有出现该错误。如果您能够执行这 2 条语句以加载所有 5 个库,然后在 EntityFramework 上出现错误,那么我们将查看具体的错误消息。
但是, 即使您能够加载所有这些 DLL,包括 EntityFramework 的两个 DLL,也不能保证您实际上能够使用英孚。有可能 EF 在 SQLCLR 中被阻止 运行ning。我不记得具体关于 EF,但我确实知道 SMO,例如,包含用于检测它是否在 SQL 服务器中 运行ning 的代码,如果是,那么它会引发一个异常说明在 SQL 服务器中不允许 运行。
Microsoft Azure Tech support has confirmed that all version of .Net 4.XX including 4.7.2 is supported in SQL Server Managed Instance CLR
托管实例使用最新版本的 .NET Framework 来托管 SQL CLR 程序集。这并不意味着它支持加载未经测试的 .NET Framework 程序集。请参阅支持声明 here。
此外,托管实例不允许使用不安全的 CLR 程序集,因为这些程序集将使您能够 运行 任意代码并直接访问服务器资源。
即使您可以将所有这些 .NET Framework 程序集加载到您的数据库中,它也不是托管实例中受支持的解决方案。上面的支持声明清楚地表明,您必须使数据库中加载的 .NET Framework 程序集的副本与服务器上的 .NET Framework 版本保持同步。服务器上的 .NET Framework 在 Windows 更新中更新。当您管理服务器时,将程序集 in-sync 与 Windows 中的版本保持一致就够难的了。但是当微软在给服务器打补丁的时候,你是没办法知道你需要更新你的程序集的。
当 运行在 Azure VM 上运行时,您将能够安装 EF 所需的所有程序集。 VM 中的唯一限制是您无法加载 mixed-mode 程序集,但我认为 EF(当前)不依赖于其中任何一个。如果您使用涉及加载到数据库中的 .NET Framework 程序集的解决方案投入生产,您可能应该实施 startup stored procedure 或计划任务,每次 Windows .NET Framework 文件夹刷新数据库程序集 SQL 服务器启动。
无论如何,这是一个 powershell 脚本,我能够将 EF6 及其依赖项加载到 SQL 服务器数据库中。但请记住,仅仅因为您可以加载程序集,并不意味着它会正常工作。您必须进行广泛的测试以确定您的 EF 代码是否真的有效。
但是 运行在您的 SQL 服务器上安装您的 .NET 代码是不寻常的,而且通常不是一个好主意。它非常接近您的数据,但同一 VNet 上的单独 VM 也是如此。它使您的 SQL 服务器更难管理,并且通常有更简单的方法来完成您希望通过 运行 在 SQL 服务器上编写代码,
此外,如果您在 SQL 服务器上本地 运行ning 您的代码,可能没有很好的理由说明它必须是 SQL CLR。您可以在控制台应用程序中 运行 您的代码并使用 xp_cmdshell 或 SQL 代理作业触发它。
无论如何,这是注册程序集的 powershell:
$constr = "server=localhost;database=clrtest;integrated security=true"
$folder = "C:\Users\dbrowne\Source\Repos\SqlClrTest\ClassLibrary1\bin\Debug"
$netfx = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
$dlls = @(
"system.dynamic",
"microsoft.csharp",
"system.componentmodel.dataannotations",
"smdiagnostics",
"system.servicemodel.internals",
"system.runtime.serialization",
"entityframework",
"entityframework.sqlserver",
"YourClassLibrary",
"YourSqlClrProject"
)
[System.Data.SqlClient.SqlConnection]$con = New-Object System.Data.SqlClient.SqlConnection $constr
$con.Open()
[System.Data.SqlClient.SqlCommand] $cmd = $con.CreateCommand()
$cmd.CommandText = @"
if cast(serverproperty('ProductMajorVersion') as int) >= 14
begin
DECLARE @hash varbinary(64);
SELECT @hash = HASHBYTES('SHA2_512', @assemblyFile);
declare @description nvarchar(4000) = @name
if not exists (select * from sys.trusted_assemblies where hash = @hash)
begin
EXEC sys.sp_add_trusted_assembly @hash = @hash,
@description = @description;
print 'trusted assembly added'
end
end
declare @sql nvarchar(max)
if exists (select * from sys.assemblies where name = @name)
begin
set @sql = concat('
alter assembly ',quotename(@name),'
FROM @assemblyFile
WITH PERMISSION_SET = UNSAFE;
')
EXECUTE sp_executesql @sql, N'@assemblyFile varbinary(max)', @assemblyFile = @assemblyFile;
print 'updated assembly ' + @name
end
else
begin
set @sql = concat('
create assembly ',quotename(@name),'
AUTHORIZATION [dbo]
FROM @assemblyFile
WITH PERMISSION_SET = UNSAFE;
')
EXECUTE sp_executesql @sql, N'@assemblyFile varbinary(max)', @assemblyFile = @assemblyFile;
print 'added assembly ' + @name
end
"@
$pName = $cmd.Parameters.Add("@name", [System.Data.SqlDbType]::NVarChar, 1000)
$pAssemblyFile = $cmd.Parameters.Add("@assemblyFile", [System.Data.SqlDbType]::VarBinary, -1)
foreach ($targetDll in $dlls)
{
try
{
$pName.Value = $targetDll
if ([System.IO.File]::Exists("$folder$targetDll.dll"))
{
$pAssemblyFile.Value = [System.IO.File]::ReadAllBytes("$folder$targetDll.dll")
}
else
{
$pAssemblyFile.Value = [System.IO.File]::ReadAllBytes("$netfx$targetDll.dll")
}
$result = $cmd.ExecuteNonQuery()
}
catch [System.Data.SqlClient.SqlException]
{
[System.Data.SqlClient.SqlException] $ex = $_.Exception
write-host "$($ex.Class) $($ex.Number) $($ex.Message) "
write-host ""
continue;
}
}
$con.Close()
Microsoft Azure 技术支持已确认在SQL 服务器托管实例 CLR 中 支持所有版本的 .Net 4.XX,包括 4.7.2。
我们正在运行使用 4.7.2 和最新的 EF 6.2 构建业务层的某些部分
https://patrickdesjardins.com/blog/how-to-use-third-party-dll-reference-in-a-sql-clr-function
因此,为了利用对经过良好测试的代码的现有投资,我们希望将某些业务层移至数据库中。
但是我们运行在发布的时候遇到了问题。
Creating [System.Dynamic]...
Warning: The Microsoft .NET Framework assembly 'system.dynamic, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.'
您正在注册的内容在 SQL 服务器托管环境中未经过全面测试,因此不受支持。将来,如果升级或维护此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。请参阅 SQL 服务器联机丛书以了解更多详细信息。
(47,1):SQL72014:.Net SqlClient 数据提供程序:
消息 6218,级别 16,状态 2,第 1 行
为程序集 'System.Dynamic' 创建程序集失败,因为程序集 'System.Dynamic' 验证失败。 检查引用的程序集是否是最新的和可信的(对于 external_access或不安全)在数据库中执行。
CLR 验证程序错误消息(如果有)将跟随此消息 [ :
System.Dynamic.ArgBuilder::MarshalToRef][mdToken=0x6000002][偏移量 0x00000000] 代码大小为零。 [: System.Dynamic.ArgBuilder::UnmarshalFromRef][mdToken=0x6000003][偏移量
P.S。 (恕我直言,EF 核心是否也无所谓,尽管我们正在使用 EF6.2 尝试此操作)
编辑: 已对我所指的所有程序集授予 UNSAFE 权限: 以下是所有依赖项:
<ItemGroup>
<Reference Include="Microsoft.CSharp">
<HintPath>..\packages2019\dotnet 4.7.2\Microsoft.CSharp.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Dynamic">
<HintPath>..\packages2019\dotnet 4.7.2\System.Dynamic.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.Runtime.Serialization">
<HintPath>..\packages2019\dotnet 4.7.2\System.Runtime.Serialization.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="SMDiagnostics">
<HintPath>..\packages2019\v4.0.30319\SMDiagnostics.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="System.ServiceModel.Internals">
<HintPath>..\packages2019\v4.0.30319\System.ServiceModel.Internals.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
<IsModelAware>True</IsModelAware>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<SpecificVersion>True</SpecificVersion>
<IsModelAware>True</IsModelAware>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<SqlPermissionSet>UNSAFE</SqlPermissionSet>
<SpecificVersion>True</SpecificVersion>
<IsModelAware>True</IsModelAware>
<GenerateSqlClrDdl>True</GenerateSqlClrDdl>
</Reference>
编辑 3:Azure 中的不安全代码 SQL 服务器 MI
编辑 4:
- 表演终结者是:
System.RunTime.Serialization
、
CREATE ASSEMBLY [System.Runtime.Serialization] AUTHORIZATION [dbo] FROM 0x4D5... WITH PERMISSION_SET = UNSAFE;
这阻止我在数据库中创建 Entity Framework 不安全程序集。我们可以通过 system.Runtime.Serialization 吗?
GO
CREATE ASSEMBLY [EntityFramework]
AUTHORIZATION [dbo]
FROM 0x4D5A90...
WITH PERMISSION_SET = UNSAFE;
GO
PRINT N'Creating [EntityFramework.SqlServer]...';
GO
CREATE ASSEMBLY [EntityFramework.SqlServer]
AUTHORIZATION [dbo]
FROM 0x4...
WITH PERMISSION_SET = UNSAFE;
Warning: The Microsoft .NET Framework assembly 'system.runtime.serialization, version=4.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089.' you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details. Msg 6218, Level 16, State 2, Line 11 CREATE ASSEMBLY for assembly 'System.Runtime.Serialization' failed because assembly 'System.Runtime.Serialization' failed verification. Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database. CLR Verifier error messages if any will follow this message [ : System.AppContextDefaultValues::PopulateDefaultValues][mdToken=0x6000001] [offset 0x00000000] Code size is zero.
SQL 服务器的 CLR 主机将使用系统上安装的最高版本的 .NET Framework,作为它链接到的 CLR 版本。 SQL Server 2005 - 2008 R2 链接到 CLR 2.0 版,因此它们将使用 .NET Framework 2.0、3.0 和 3.5 版。 SQL Server 2012 及更新版本都链接到 CLR 4.0 版,因此将使用 .NET Framework 版本 4.x.
也就是说,有些框架库是 built-in,不需要手动添加。这些列在这里:
Supported .NET Framework Libraries
如果您需要的库不在该列表中,您可以自己添加,但是这并不意味着您可以添加任何库。 SQL 服务器只允许纯 MSIL 库,不允许混合模式(混合 = 包含托管和非托管代码)。如果您需要一个混合模式的库,那么您无法将其加载到 SQL 服务器中。另外,请记住,即使今天的库是纯 MSIL,也不意味着它不能在未来的框架更新中转换为混合模式(是的,这已经发生了)。
考虑到所有这些,错误消息中的以下项目:
Code size is zero.
可能表示您正在尝试加载参考库。您需要加载 actual 库,而不是它的参考版本。
我在 SQL Server 2017 上尝试了以下操作,并且能够全部加载它们,但并非所有都需要显式加载。有些自动加载其他的,因为它们在同一个文件夹中:
CREATE ASSEMBLY [Microsoft.CSharp]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.CSharp.dll'
WITH PERMISSION_SET = UNSAFE;
-- includes System.Dynamic
CREATE ASSEMBLY [System.Runtime.Serialization]
FROM 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE;
-- includes SMDiagnostics, System.ServiceModel.Internals
然后检查:
SELECT * FROM sys.assemblies;
/*
Microsoft.CSharp
System.Dynamic
System.Runtime.Serialization
System.ServiceModel.Internals
SMDiagnostics
*/
请注意,目前我将数据库设置为 TRUSTWORTHY ON
。这不是我通常推荐的东西,也可能不是必需的,但在我完成我的 post 处理如何正确地 和轻松地 、TRUSTWORTHY
之前就够了。
我没有要加载的 EntityFramework 库,但是您遇到的错误是第一个,而我在上面 post 编写的语句没有出现该错误。如果您能够执行这 2 条语句以加载所有 5 个库,然后在 EntityFramework 上出现错误,那么我们将查看具体的错误消息。
但是, 即使您能够加载所有这些 DLL,包括 EntityFramework 的两个 DLL,也不能保证您实际上能够使用英孚。有可能 EF 在 SQLCLR 中被阻止 运行ning。我不记得具体关于 EF,但我确实知道 SMO,例如,包含用于检测它是否在 SQL 服务器中 运行ning 的代码,如果是,那么它会引发一个异常说明在 SQL 服务器中不允许 运行。
Microsoft Azure Tech support has confirmed that all version of .Net 4.XX including 4.7.2 is supported in SQL Server Managed Instance CLR
托管实例使用最新版本的 .NET Framework 来托管 SQL CLR 程序集。这并不意味着它支持加载未经测试的 .NET Framework 程序集。请参阅支持声明 here。
此外,托管实例不允许使用不安全的 CLR 程序集,因为这些程序集将使您能够 运行 任意代码并直接访问服务器资源。
即使您可以将所有这些 .NET Framework 程序集加载到您的数据库中,它也不是托管实例中受支持的解决方案。上面的支持声明清楚地表明,您必须使数据库中加载的 .NET Framework 程序集的副本与服务器上的 .NET Framework 版本保持同步。服务器上的 .NET Framework 在 Windows 更新中更新。当您管理服务器时,将程序集 in-sync 与 Windows 中的版本保持一致就够难的了。但是当微软在给服务器打补丁的时候,你是没办法知道你需要更新你的程序集的。
当 运行在 Azure VM 上运行时,您将能够安装 EF 所需的所有程序集。 VM 中的唯一限制是您无法加载 mixed-mode 程序集,但我认为 EF(当前)不依赖于其中任何一个。如果您使用涉及加载到数据库中的 .NET Framework 程序集的解决方案投入生产,您可能应该实施 startup stored procedure 或计划任务,每次 Windows .NET Framework 文件夹刷新数据库程序集 SQL 服务器启动。
无论如何,这是一个 powershell 脚本,我能够将 EF6 及其依赖项加载到 SQL 服务器数据库中。但请记住,仅仅因为您可以加载程序集,并不意味着它会正常工作。您必须进行广泛的测试以确定您的 EF 代码是否真的有效。
但是 运行在您的 SQL 服务器上安装您的 .NET 代码是不寻常的,而且通常不是一个好主意。它非常接近您的数据,但同一 VNet 上的单独 VM 也是如此。它使您的 SQL 服务器更难管理,并且通常有更简单的方法来完成您希望通过 运行 在 SQL 服务器上编写代码,
此外,如果您在 SQL 服务器上本地 运行ning 您的代码,可能没有很好的理由说明它必须是 SQL CLR。您可以在控制台应用程序中 运行 您的代码并使用 xp_cmdshell 或 SQL 代理作业触发它。
无论如何,这是注册程序集的 powershell:
$constr = "server=localhost;database=clrtest;integrated security=true"
$folder = "C:\Users\dbrowne\Source\Repos\SqlClrTest\ClassLibrary1\bin\Debug"
$netfx = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
$dlls = @(
"system.dynamic",
"microsoft.csharp",
"system.componentmodel.dataannotations",
"smdiagnostics",
"system.servicemodel.internals",
"system.runtime.serialization",
"entityframework",
"entityframework.sqlserver",
"YourClassLibrary",
"YourSqlClrProject"
)
[System.Data.SqlClient.SqlConnection]$con = New-Object System.Data.SqlClient.SqlConnection $constr
$con.Open()
[System.Data.SqlClient.SqlCommand] $cmd = $con.CreateCommand()
$cmd.CommandText = @"
if cast(serverproperty('ProductMajorVersion') as int) >= 14
begin
DECLARE @hash varbinary(64);
SELECT @hash = HASHBYTES('SHA2_512', @assemblyFile);
declare @description nvarchar(4000) = @name
if not exists (select * from sys.trusted_assemblies where hash = @hash)
begin
EXEC sys.sp_add_trusted_assembly @hash = @hash,
@description = @description;
print 'trusted assembly added'
end
end
declare @sql nvarchar(max)
if exists (select * from sys.assemblies where name = @name)
begin
set @sql = concat('
alter assembly ',quotename(@name),'
FROM @assemblyFile
WITH PERMISSION_SET = UNSAFE;
')
EXECUTE sp_executesql @sql, N'@assemblyFile varbinary(max)', @assemblyFile = @assemblyFile;
print 'updated assembly ' + @name
end
else
begin
set @sql = concat('
create assembly ',quotename(@name),'
AUTHORIZATION [dbo]
FROM @assemblyFile
WITH PERMISSION_SET = UNSAFE;
')
EXECUTE sp_executesql @sql, N'@assemblyFile varbinary(max)', @assemblyFile = @assemblyFile;
print 'added assembly ' + @name
end
"@
$pName = $cmd.Parameters.Add("@name", [System.Data.SqlDbType]::NVarChar, 1000)
$pAssemblyFile = $cmd.Parameters.Add("@assemblyFile", [System.Data.SqlDbType]::VarBinary, -1)
foreach ($targetDll in $dlls)
{
try
{
$pName.Value = $targetDll
if ([System.IO.File]::Exists("$folder$targetDll.dll"))
{
$pAssemblyFile.Value = [System.IO.File]::ReadAllBytes("$folder$targetDll.dll")
}
else
{
$pAssemblyFile.Value = [System.IO.File]::ReadAllBytes("$netfx$targetDll.dll")
}
$result = $cmd.ExecuteNonQuery()
}
catch [System.Data.SqlClient.SqlException]
{
[System.Data.SqlClient.SqlException] $ex = $_.Exception
write-host "$($ex.Class) $($ex.Number) $($ex.Message) "
write-host ""
continue;
}
}
$con.Close()