在开发了能够使用EzAPI为SQL Server自动生成DTSX包的软件之后,同时还包含了一个带有Web客户端的脚本任务,奇怪的事情开始发生了。
脚本任务引用来自GAC的DLL,该DLL使用反射调用API来完成任务。
下面是一些奇怪的事情:
导出SQL server 2012的软件包后,如果我将其部署在SQL Server 2012上,它可以工作,但不能与远程服务器通信。另一方面,同样适用于SQL server 2012的软件包,如果我将其部署到较新版本的SQL Server,它可以正常工作并与远程服务器通信。
一旦我为SQL server 2014导出软件包,如果我将其部署在SQL Server 2014上,它可以工作,但不能与远程服务器通信。另一方面,同样适用于SQL server 2014的软件包,如果我将其部署到较新版本的SQL Server,它可以正常工作并与远程服务器通信。
一旦我导出SQL server 2016的包,如果我将其部署在SQL Server 2016上,它可以工作,但不能与远程服务器通信。另一方面,同样适用于SQL server 2016的包,如果我将其部署到较新版本的SQL Server,它可以正常工作并与远程服务器通信。
此外,似乎如果我用DataTools或Visual Studio打开包,它可以工作,但不能与远程服务器通信。另一方面,如果我重新构建脚本任务,那么它就可以工作并与远程服务器通信。
我的结论是,迁移会迫使脚本任务重新构建代码,这就是在更高版本中部署时需要工作的原因。
但是不知道为什么不迁移或重建代码就不能工作。请注意,2014年的套餐在2014年不起作用,但在2016年起作用。此外,2012年的软件包在2012年不起作用,但同样的软件包在2014年起作用。所以问题不是SQL的版本,也不是任何代码的问题。
此外,在通过VSTA进行开发时,我们故意在脚本任务中犯了语法错误,但脚本任务已成功构建,并且我们在SQL Server 2012上部署了程序包。报告通过SSIDB成功执行该包,而不执行任何操作。另一方面,我们将SQL Server 2012的相同程序包部署到SQL Server 2014,SSMS报告该程序包无法构建脚本任务。
现在看来,在同一版本的SQL Server中部署脚本任务时,脚本任务会被绕过,并且总是返回成功。
有什么想法吗?
发布于 2020-11-27 16:35:57
最后,在深入研究这个问题之后,我发现了问题,通常我会删除我的问题,但无论如何,这揭示了Microsoft工具内部正在发生的事情,因此可能会有所帮助。
通常,代码应该遵循特定的步骤来创建脚本任务,嵌入到包中的代码如下所示。
// 1. Create a script task
var th = (TaskHost)exec;
th.Name = "Script Task";
th.Description = "This is a Script Task";
var task = (ScriptTask)th.InnerObject;
// 2. Set the script language - "CSharp" or "VisualBasic"
task.ScriptLanguage = VSTAScriptLanguages.GetDisplayName("CSharp");
// 3. Set any variables used by the script
//task.ReadWriteVariables = "User::Var1, User::Var2";
// 4. Create a new project from the template located in the default path
task.ScriptingEngine.VstaHelper.LoadNewProject(task.ProjectTemplatePath, null, "MyScriptProject");
// 5. Initialize the designer project, add a new code file, and build
//task.ScriptingEngine.VstaHelper.Initalize("", true);
//task.ScriptingEngine.VstaHelper.AddFileToProject("XX.cs", "FileContents");
//task.ScriptingEngine.VstaHelper.Build("");
// 6. Persist the VSTA project + binary to the task
if (!task.ScriptingEngine.SaveProjectToStorage())
{
throw new Exception("Save failed");
}
// 7. Use the following code to replace the ScriptMain contents
var contents = File.ReadAllText("path to file");
var scriptFile =
task.ScriptStorage.ScriptFiles["ScriptMain.cs"] =
new VSTAScriptProjectStorage.VSTAScriptFile(VSTAScriptProjectStorage.Encoding.UTF8, contents);
// 8. Reload the script project, build and save
task.ScriptingEngine.LoadProjectFromStorage();
task.ScriptingEngine.VstaHelper.Build("");
// 9. Persist the VSTA project + binary to the task
if (!task.ScriptingEngine.SaveProjectToStorage())
{
throw new Exception("Save failed");
}向前看起来很奇怪,对吧?
如果您忘记了最后一组代码行(.9),会发生什么情况?
// 9. Persist the VSTA project + binary to the task
if (!task.ScriptingEngine.SaveProjectToStorage())
{
throw new Exception("Save failed");
}然后魔术开始发生,包定义将包含您的实际代码,但二进制文件仍将是旧的Intiatilize脚本的映像,该脚本总是返回成功。
在这种情况下,如果您将包部署到同一版本的SQL Server,SQL Server将不会生成您的代码,因为已经有了一个,这是错误的。另一方面,如果您部署在更高版本的SQL Server上,包定义会发生变化,因此,它会构建您的实际脚本,然后它就可以工作了。
对于DataTools / VisualStudio也是如此,如果您使用DataTools / VisualStudio打开包并执行它,它将在定义中执行构建,该定义是原始初始化脚本的映像。另一方面,如果您打开脚本,脚本将根据代码重新构建,并且它将在下一次执行中工作。
https://stackoverflow.com/questions/65013423
复制相似问题