EPPlus 2.9.0.1 создает исключение System.IO.IsolatedStorage.IsolatedStorageException при попытке сохранить файл размером более ~1,5 МБ из пакета служб SSIS.
Эта проблема
Когда я пытаюсь сохранить файл размером ~1,5 МиБ с EPPlus ExcelPackage.Save()
бросает System.IO.IsolatedStorage.IsolatedStorageException
,
Объяснение
Я создаю пакет служб SSIS с Visual Studio 2008 9.0.30729.4462 QFE
а также .NET Framework 3.5 SP1
экспортировать содержимое SQL Server 2008 SP2 10.0.4311.0 64 bit
стол через EPPlus 2.9.0.1
библиотека.
Пакет служб SSIS действительно прост:Execute SQL Task
который читает содержимое таблицы и помещает ее в переменную, за которой следуетScript task
который читает переменную набора записей и сохраняет содержимое на диск через EPPlus.
Код задачи скрипта:
namespace ST_00a0b40814db4c7290b71f20a45b62c6.csproj
{
using System;
using System.AddIn;
using System.Data;
using System.Data.OleDb;
using System.IO;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Tasks.ScriptTask;
using OfficeOpenXml;
[AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : VSTARTScriptObjectModelBase
{
public void Main()
{
DataTable documentList = new DataTable();
using (OleDbDataAdapter adapter = new OleDbDataAdapter())
{
adapter.Fill(documentList, this.Dts.Variables["DocumentList"].Value);
}
if (documentList.Rows.Count > 0)
{
FileInfo fileInfo = new FileInfo(@"C:\Temp\Test.xlsx");
if (fileInfo.Exists)
{
fileInfo.Delete();
}
using (ExcelPackage package = new ExcelPackage(fileInfo))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Documents");
for (Int32 i = 0; i < documentList.Rows.Count; i++)
{
for (Int32 j = 0; j < documentList.Columns.Count; j++)
{
worksheet.Cells[i + 1, j + 1].Value = documentList.Rows[i][j];
}
}
package.Save();
}
}
Dts.TaskResult = Convert.ToInt32(DTSExecResult.Success);
}
}
}
Когда я передаю "Задачу сценария" только пару записей, пакет работает нормально, но когда я запускаю его для полной таблицы,package.Save();
взрывается сSystem.IO.IsolatedStorage.IsolatedStorageException: Unable to determine the identity of domain
исключение.
Здесь вы можете увидеть полную трассировку стека:
Error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Error saving file C:\Temp\Test.xls ---> 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 System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain()
at MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder.GetCurrentStore()
at MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder..ctor()
at MS.Internal.IO.Packaging.PackagingUtilities.GetDefaultIsolatedStorageFile()
at MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32 retryCount, String& fileName)
at MS.Internal.IO.Packaging.SparseMemoryStream.EnsureIsolatedStoreStream()
at MS.Internal.IO.Packaging.SparseMemoryStream.SwitchModeIfNecessary()
at MS.Internal.IO.Packaging.SparseMemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Packaging.CompressEmulationStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Packaging.CompressStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(String value)
at System.IO.TextWriter.Write(String format, Object arg0, Object arg1)
at OfficeOpenXml.ExcelWorksheet.UpdateRowCellData(StreamWriter sw)
at OfficeOpenXml.ExcelWorksheet.SaveXml()
at OfficeOpenXml.ExcelWorksheet.Save()
at OfficeOpenXml.ExcelWorkbook.Save()
at OfficeOpenXml.ExcelPackage.Save()
--- End of inner exception stack trace ---
at OfficeOpenXml.ExcelPackage.Save()
at ST_00a0b40814db4c7290b71f20a45b62c6.csproj.ScriptMain.Main() in C:\Temp\ScriptMain.cs:line 39
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, CultureInfo culture)
at Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()
Я смог точно определить проблему по размеру сгенерированного файла: когда размер файла Excel увеличивается примерно на 1,5 МБ (это более или менее значение, я не смог найти точный размер), ошибка обнаруживается.
Единственная информация, которую мне удалось найти в сети, - это сообщение в блоге. Там блоггер предлагает решение, в котором он "переводит" код на внешний источник в DLL, загружает его в GAC сервера и затем выполняет следующий код:
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = rootPath;
setup.DisallowBindingRedirects = false;
setup.DisallowCodeDownload = true;
setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
Evidence evidence = new Evidence();
evidence.AddHost(new Zone(SecurityZone.MyComputer));
AppDomain ad = AppDomain.CreateDomain("NewAppDomain", evidence, setup);
YourClass yourClass = (YourClass)ad.CreateInstanceAndUnwrap(typeof(YourClass).Assembly.FullName, typeof(YourClass).FullName);
yourClass.aMethod();
AppDomain.Unload(ad);
Однако я не могу попробовать это решение, потому что у меня нет доступа к GAC сервера, и я не могу загрузить DLL.
Есть ли другой способ обойти эту проблему?
Я также открыл отчет об ошибках на трекере проблем EPPlus по этому вопросу.
Резюме
- Пакет служб SSIS
- Visual Studio 2008 9.0.30729.4462 QFE
- .NET Framework 3.5 SP
- SQL Server 2008 с пакетом обновления 2 (SP2) 10.0.4311.0, 64-разрядная версия
- EPPlus 2.9.0.1
- Большой выходной файл
- System.IO.IsolatedStorage.IsolatedStorageException: невозможно определить личность домена
1 ответ
Оказывается, вам не нужно создавать совершенно новую DLL и загружать ее в GAC, чтобы это работало. Вы можете просто создать новый экземпляр вашего исходного класса (или новый класс с методами, которые вам нужно вызвать) в другом домене приложения.
1) Возьмите код, который вызывает исключение, и поместите его в отдельный метод. Убедитесь, что все объекты, которые будут переданы внутрь или наружу, либо Serializable, либо расширяют MarshalByRefObject. В твоем случае:
public void SavePackage(FileInfo fileInfo, DataTable documentList)
{
using (ExcelPackage package = new ExcelPackage(fileInfo))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Documents");
for (Int32 i = 0; i < documentList.Rows.Count; i++)
{
for (Int32 j = 0; j < documentList.Columns.Count; j++)
{
worksheet.Cells[i + 1, j + 1].Value = documentList.Rows[i][j];
}
}
package.Save();
}
}
2) Создайте новый экземпляр вашего класса, используя код, который вы упомянули выше.
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
evidence.AddAssembly(Assembly.GetExecutingAssembly().FullName);
evidence.AddHost(new Zone(SecurityZone.MyComputer));
AppDomain ad = AppDomain.CreateDomain(DomainName, evidence, setup);
ScriptMain mainClass = (ScriptMain)ad.CreateInstanceAndUnwrap(typeof(ScriptMain).Assembly.FullName, typeof(ScriptMain).FullName);
3) Вызовите метод, затем выгрузите AppDomain.
try
{
mainClass.SavePackage(fileInfo, documentList);
}
finally
{
AppDomain.Unload(ad);
}