C# 如何在SSIS脚本任务中为动态加载的程序集启动新的应用程序域
我已经构建了一个程序集,可以调用ClosedXML库。在我导出大型Excel文件之前,一切都很正常, 然后事情发生了变化,我收到了以下例外情况:C# 如何在SSIS脚本任务中为动态加载的程序集启动新的应用程序域,c#,ssis,appdomain,closedxml,C#,Ssis,Appdomain,Closedxml,我已经构建了一个程序集,可以调用ClosedXML库。在我导出大型Excel文件之前,一切都很正常, 然后事情发生了变化,我收到了以下例外情况: System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain. at System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(Evidence evide
System.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain.
at System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, Object& oNormalized)
at System.IO.IsolatedStorage.IsolatedStorage.GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, String& typeName, String& instanceName)
at System.IO.IsolatedStorage.IsolatedStorage._InitStore(IsolatedStorageScope scope, Evidence domainEv, Type domainEvidenceType, Evidence assemEv, Type assemblyEvidenceType, Evidence appEv, Type appEvidenceType)
at System.IO.IsolatedStorage.IsolatedStorage.InitStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)
at System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)
at MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder.GetCurrentStore()...
因此,经过一些研究,我发现了一些关于如何解决上述例外情况的信息,这些信息在下面的问题中有详细说明:
正如在回答上述问题时所建议的,我确保自定义程序集中的所有类都继承自MarshalByRefObject
,并标记为Serializable
。
我还添加了一个自定义程序集resolveventhandler
也就是说,由于我在运行时从一个文件加载程序集(之所以这样做是因为我没有将其添加到GAC的选项),因此我很难确定如何正确实现新域及其解析事件。当我执行下面的代码时,我收到以下错误:
repository.GetWorkFlows()
被调用:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''System.MarshalByRefObject' does not contain a definition for 'GetWorkFlows''
代码:
using System;
using System.Data.SqlClient;
using System.Reflection;
namespace ST_1736b3ab1e134250a6c05bffb44d449f
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public Assembly CustomResolveEventHandler(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
try
{
assembly = LoadAssembly(args, assembly);
}
catch (Exception exception)
{
Dts.Log(exception.ToString(), 0, new byte[0]);
throw;
}
Dts.Log("Exiting CurrentDomain_AssemblyResolve", 0, new byte[0]);
return assembly;
}
public Assembly LoadAssembly(ResolveEventArgs args, Assembly assembly)
{
Dts.Log(string.Format("Entering CurrentDomain_AssemblyResolve with args.Name [{0}]", args.Name), 0, new byte[0]);
string referencedAssembliesFilePath = Dts.Variables["$Package::referencedAssembliesFilePath"].Value.ToString();
var assemblyName = string.Format("{0}.dll", args.Name.Split(',')[0]);
Dts.Log("Assembly Name: " + assemblyName, 0, new byte[0]);
var assemblyFilePath = System.IO.Path.Combine(referencedAssembliesFilePath, assemblyName);
if (System.IO.File.Exists(assemblyFilePath))
{
Dts.Log(string.Format("Currently Loading [{0}]", assemblyFilePath), 0, new byte[0]);
assembly = Assembly.LoadFile(assemblyFilePath);
}
else
{
Dts.Log(string.Format("Could Not Find Assembly File [{0}].", assemblyFilePath), 0, new byte[0]);
}
return assembly;
}
public void Main()
{
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory.ToString();
Evidence evidence = new Evidence();
evidence.AddHostEvidence(new Zone(System.Security.SecurityZone.MyComputer));
AppDomain domain = AppDomain.CreateDomain("SeparateDomain", evidence, setup);
separateDomain.AssemblyResolve += new ResolveEventHandler(CustomResolveEventHandler);
const string referencedAssemblyName = "SSISDataExportManager";
string query = Dts.Variables["$Package::queryGetDataExportWorkFlowTasks"].Value.ToString();
dynamic repository = separateDomain.CreateInstanceAndUnwrap(referencedAssemblyName, referencedAssemblyName + "." + "DataExportManagerRepository");
using (SqlConnection connection = (SqlConnection)Dts.Connections["DbConnection"].AcquireConnection(Dts.Transaction))
{
if (connection.State == System.Data.ConnectionState.Closed) connection.Open();
//***Exception thrown here***
dynamic workflows = repository.GetWorkFlows(connection, query, 60);
dynamic factory = separateDomain.CreateInstanceAndUnwrap(referencedAssemblyName, "DataExportWorkflowSessionFactory");
dynamic session = factory.CreateSession(workflows);
session.Execute(connection);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
#region ScriptResults declaration
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
}
}
我假设这是因为我需要显式地强制转换到自定义程序集中的类型,但同样,我不能这样做,因为它开始动态加载
我错过了什么?有没有其他方法可以做到这一点,或者说这是可能的 出于好奇,在64位模式下运行包(默认开发将是32位模式)是否允许AppDomain比您所经历的更大?在调试器之外运行它怎么样,因为这会严重影响资源分配的规模。64位模式是右键单击dtproj、属性、生成、编译?在调试器之外运行需要在授权服务器上运行包(dev许可证可以)。最后,它似乎要检查SQL Server Integration Services服务是否安装在机箱上。@billinkc我还没有尝试过它,但我会试一试,看看结果如何。