我对这个主题做了一些简单的研究,我想知道所有的优点和缺点,或者在 SQL Server 中启用/注册这个特定的 .dll 是什么?
返回信息 - 我们正在与第三方应用程序集成(不幸的是,这不是我的决定),其中一些需要此 .dll 其他 .dll。我需要 CLR 函数的目的是能够在 SSMS 中编写 SQL 查询,并将该数据发送到第三方应用程序的 API,然后该 API 将执行正确的数据加载/更改(插入和删除此应用程序有通过其 API 完成)。
编辑 - 也许我应该包括这个细节
在尝试注册我的 c# 类时,我显然得到了错误“system.web not registered blah blah blah”,这反过来又促使我对这个主题进行研究。
结束编辑
所以,我的难题是,为了能够注册我的 C# 类/.dll,我必须注册所有依赖的 .dll,但是根据我的研究,我知道这个特定的可能会很成问题。
所以看到我对谷歌研究之外的陷阱不是很熟悉,我想知道你们中的一个人是否可以帮助我了解如何在这方面做出最好的决定。
另外,我还能在这篇文章中添加什么,以便更容易提供洞察力?我不太确定 C# 代码是否相关?我知道这可能有点宽泛,但我希望它足够具体以至于不会被标记?
更具体地说明这里发生的事情(根据所罗门的要求)
第 3 方应用程序使用“API”(松散地使用,因为我被告知它不是一个很好的 API)来来回发送数据。你会注意到它调用了一个 Importer 函数,该函数只接受一个数据表或它转换的 excel 文件。我没有其他选择,因为该公司告诉我,通过普通 XML 插入和删除非常慢并且有意外行为。
引用 System.Web 的 .DLL 在我的 C# 类中被引用,这是首先能够向其发送数据所必需的。
关于:
为什么你不能使用我提到的方法?它们已经存在于 SQL Server 的 CLR 主机中。这是一个网络服务,对吧
我不确定我对 API 的了解是否足以回答这个问题。我很可能也只是缺乏这样做的知识和经验。这也可能是因为我对如何与这个特定的 API 交互有限制,我不确定这些限制如何应用于这些方法。(我将进一步调查,看看我是否可以自己回答这个问题)。
虽然我想得越多,我可以创建一个 SQL Server 可以调用的“中间人”类,然后它会调用另一个类,该类将具有所有正确的引用,这可能会让我摆脱目前的情况。但是,我仍然对具体的反馈感兴趣,以便从中学习。
这是我的 C# 类:
using Perfion.Api; -- this .DLL references System.Web.
using Perfion.Api.Import;
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace PerfInsert
{
public static class PerfionInsert
{
public static bool CreateCommand(string tblString, string featureName, string connectionString, string perfionConnectionString, string logFile)
{
StringBuilder logInfo = new StringBuilder();
try
{
var wList = new Regex(@"[^0-9a-z\.\[\]_]#", RegexOptions.IgnoreCase);
if (wList.IsMatch(tblString))
{
logInfo.AppendLine($"{DateTime.UtcNow} - Regex Validation Failed for Table Name!");
return false;
}
using (SqlConnection connection = new SqlConnection(connectionString))
{
var qryString = "SELECT * FROM " + tblString;
using (SqlCommand command = new SqlCommand(qryString, connection))
{
connection.Open();
using (var dataReader = command.ExecuteReader())
using (var dataTable = new DataTable())
{
dataTable.Load(dataReader);
PerfionApi api = new PerfionApi(perfionConnectionString);
Importer importer = new Importer(api.Connection);
importer.Status += (sender, e) => { logInfo.AppendLine($"{DateTime.UtcNow} - {e.Title}"); };
importer.LoadData(dataTable);
importer.ImportToDatabase(featureName);
}
}
}
return true;
}
catch (Exception ex)
{
logInfo.AppendLine($"{DateTime.UtcNow} - {ex.ToString()}");
}
finally
{
File.AppendAllText(logFile, logInfo.ToString());
}
return false;
}
}
}
3rd 方软件需要 DLL 在这里似乎无关紧要。看来问题很简单:
我相信你最好的两个选择是:
如果此过程如您所说的那样简单,并且您真的想坚持使用
System.Web
,那么为什么不创建一个控制台应用程序来执行查询,然后将您需要的任何内容发布到 API 中呢?如果需要定期执行此操作,可以在 Windows 任务计划程序或 SQL Server 代理中进行计划(通过“操作系统 (CmdExec)”作业步骤)。如果此过程稍微复杂一些和/或您需要能够以更动态/特别的方式执行这些查询,则
System.Web
不需要,它只是使一些编码更容易。Intead,查看HttpWebRequest和HttpWebResponse。这两个包含在 中System.Net
,这是 SQLCLR 支持的 .NET Framework 库之一。主要区别在于您需要手动构建 XML 请求。处理响应也是如此。这种方法比导入更稳定和安全System.Web
。按照这些思路,对于任何需要此类功能但不想(或不能)对其进行编码的人,我编写了一个 SQLCLR 函数和过程库 — SQL# — 其中包括一个存储过程INET_GetWebPages,它实现了这两种方法。虽然有免费版本,但此特定存储过程仅在完整(即付费)版本中可用。但是,它确实处理了各种选项/场景,包括:设置各种 HTTP 标头、可选的基本身份验证、代理服务器、发送 GET 与 POST 数据、处理 PUT 请求以及减少对性能的潜在负面影响的选项。
如果您说您正在使用 3rd 方应用程序的 DLL 通过他们提供的方法进行 API 调用,并且引用和使用的是他们的 DLL
System.Web
(而不是您的代码直接),那么很难完全肯定地说所有的影响都是。但这里有一些关于这种方法需要考虑的事情:System.Web
不在SQLCLR支持的 .NET Framework 库列表中。这至少意味着:UNSAFE
. 这本质上不是问题,但确实允许很容易成为问题的行为。例如,如果此第 3 方 DLL 使用的任何代码路径使用静态变量来缓存信息,如果该值不是标准的(即它可以在调用此代码之间甚至期间更改),那么您可以由于 SQL Server 使用共享的应用程序域并且所有会话共享相同的内存/静态数据,因此进入竞争状态。UNSAFE
由于不在“支持”列表中,因此必须加载一些代码,并且它包含违反安全策略的内容,即使您永远不会使用该特定代码路径。在这些情况下,代码在技术上可以是“安全的”,但如果没有看到源代码,你就无法确定。所以你需要测试,但测试需要超过 1 个人点击几次:它需要多个并发会话点击此代码以查看是否存在竞争条件。但是还有其他更难测试的场景,例如由于异常导致的内存泄漏。受支持的库中的某些方法因此受到限制,但可能没有人知道不受支持的库中的方法是否存在此类问题,因为我不相信它们已经过测试。如果此功能旨在非面向用户(即系统进程、公司内部功能等),那么您可以通过启动 SQL Server Express 实例并加载来缓解大多数问题(安全性、性能、稳定性)你在那里的项目。这会将非理想 SQLCLR 功能与您的生产应用程序隔离/隔离。假设您已经在使用常规的外部
SqlConnection
(不是内部/受信任的连接),那么这不需要对您的代码进行任何更改。使用这种方法(即,将 SQLCLR 项目加载到隔离实例中)无法减轻的唯一风险是,如果 Microsoft 更新
System.Web
(或将其加载到 SQL Server 时被吸入的任何依赖项),代码可能会中断是一个混合模式库。这可能永远不会发生,但如果发生了,那么除非他们切换到 using ,否则您将无法加载该 3rd 方 DLLHttpWebRequest
,而且他们几乎没有理由进行此类更改。更新
OP 回复了一个相关问题,他们选择将项目类型更改为控制台应用程序,并且最有可能使用 SQL 代理来安排它(但也可以使用 Windows 任务计划程序
相关文章(在 StackOverflow 上):