2

I have built an assembly that make calls to the ClosedXML library. Everything works perfectly until I have to export large Excel files, then things go south and I receive the following exception:

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()...

So, after some research, I found some info on how to address the above exception, which is detailed in the questions below:

EPPlus 2.9.0.1 throws System.IO.IsolatedStorage.IsolatedStorageException when trying to save a file bigger than ~1.5 MiB from a SSIS package

Unable to determine the identity of domain using System.IO.Packaging

Isolated Storage Exception: Unable to determine the identity of domain

As suggested in the answers to the questions above, I made sure that all of the classes in my custom assembly inherit from MarshalByRefObject and are marked as Serializable. I have also added a custom assembly ResolveEventHandler.

Saying that, because I am loading the assembly from a file at runtime (this is done because I do not have the option of adding it to the GAC), I am having trouble figuring out how to correctly implement the new domain and its resolve event. When I execute the code below, I recieve following error: repository.GetWorkFlows() is called:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''System.MarshalByRefObject' does not contain a definition for 'GetWorkFlows''

Code:

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

    }
}

I assume that this is because I need to explicitly cast to the types in my custom assembly, but again, I cannot do this due to it begin dynamically loaded.

What am I missing? Is there another way to do this, or is this even possible?

rickmanalexander
  • 599
  • 1
  • 6
  • 17
  • Out of curiosity, does running the package in 64 bit mode (default development will be 32 bit mode) allow the AppDomain to go larger than what you're experiencing? What about running it outside debugger as that places a heavy finger on the scales of resource allocation. 64 bit mode is Right click dtproj, Properties, Build, Compilation? Running outside of the debugger requires the packages run on a licensed server (dev license is fine). Ultimately, it seems to check on whether the SQL Server Integration Services Service is installed on the box. – billinkc Jun 02 '20 at 14:05
  • @billinkc I haven't tried it yet but I'll give it a shot and see what comes of it. – rickmanalexander Jun 03 '20 at 23:54

0 Answers0