/// <summary> /// Загрузка файла представления контента в хранилище системы ECR /// </summary> /// <param name="ItemKey">Товарный ключ позиции</param> /// <param name="ItemNumber">Номер позиции</param> /// <param name="ItemBody">Тело файла</param> /// <param name="ViewName">Идентификатор представления контента</param> public void TransferView(string ItemKey, int?ItemNumber, byte[] ItemBody, string ViewName) { var reader = new ECRManagedDataReader(_baseServerName, _connectionTimeout, _commandTimeout); using (var conn = new SqlConnection((reader.GetStorageForView(ViewName)).Tables[0].Rows[0]["ConnectionString"].ToString())) { conn.Open(); try { var cmd = new SqlCommand("[ecr].[UpdateViewItem]", conn) { CommandType = CommandType.StoredProcedure, CommandTimeout = DEFAULT_COMMAND_TIMEOUT }; cmd.Parameters.AddWithValue("@DisplayAlias", reader.GetViewAliasByName(ViewName)); cmd.Parameters.AddWithValue("@ItemKey", ItemKey); if (ItemNumber != null) { if (ItemNumber > 0) { cmd.Parameters.AddWithValue("@ItemNumber", ItemNumber); } else { cmd.Parameters.AddWithValue("@ItemNumber", DBNull.Value); } } else { cmd.Parameters.AddWithValue("@ItemNumber", DBNull.Value); } if (ItemBody != null) { // Важно: передача массива нулевой длины приравнивается к передаче значения null (~ удалению даных) if (ItemBody.Length > 0) { cmd.Parameters.AddWithValue("@ItemBody", ItemBody); } else { cmd.Parameters.Add("@ItemBody", SqlDbType.VarBinary); cmd.Parameters["@ItemBody"].Value = DBNull.Value; } } else { cmd.Parameters.Add("@ItemBody", SqlDbType.VarBinary); cmd.Parameters["@ItemBody"].Value = DBNull.Value; } cmd.CommandTimeout = DEFAULT_COMMAND_TIMEOUT; cmd.ExecuteNonQuery(); } finally { conn.Close(); } } }
/// <summary> /// Процедура возвращает объект ADODB.Recordset, предоставляющий данные об элементе файлового контента (представление), соответствующему заданным параметрам; /// Исторические данные по представлениям файлового контента в хранилищах системы ECR не хранятся; /// </summary> /// <param name="ViewName">Системное имя объекта View (тип файлового контента, представления)</param> /// <param name="ItemKey">Ключ элемента. Основной параметр идентификации</param> /// <param name="ItemNumber">Номер элемента. Значение "0" эквивалентно null для немножественных типов файлового контента</param> /// <returns>ADODB.Recordset. Набор данных файлового контента (представляения, объект ViewData), соответствующий заданному элементу</returns> public ADODB.Recordset GetViewItem(string ViewName, string ItemKey, int ItemNumber) { try { var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); return(DataSetConverter.DataSetConverter.ConvertToADODBRecordset(_reader.GetViewItem(ViewName, ItemKey, ItemNumber))); } catch (Exception e) { LogEvent(string.Format("GetViewItem() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(null); }
/// <summary> /// Процедура возвращает целочисленный псевдоним объекта Storage по его системному имени; /// </summary> /// <param name="SystemName">Системное имя объекта Storage</param> /// <returns>Целочисленный псевдоним объекта Storage</returns> public int GetStorageAliasByName(string SystemName) { try { var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); return(_reader.GetStorageAliasByName(SystemName)); } catch (Exception e) { LogEvent(string.Format("GetStorageAliasByName() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(0); }
/// <summary> /// Процедура возвращает системное имя объекта Storage по его целочисленному псевдониму; /// </summary> /// <param name="DisplayAlias">Целочисленный псевдоним объекта Storage</param> /// <returns>String. Системное имя объекта Storage</returns> public string GetStorageNameByAlias(int DisplayAlias) { try { var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); return(_reader.GetStorageNameByAlias(DisplayAlias)); } catch (Exception e) { LogEvent(string.Format("GetStorageNameByAlias() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(null); }
/// <summary> /// Процедура осуществляет проверку признака множественности объекта View с заданным системным именем; /// </summary> /// <param name="SystemName">Системное имя для объекта View</param> /// <returns>Bool. Признак множественности объекта View с заданным системным именем</returns> public bool IsViewMultiplied(string SystemName) { try { var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); return(_reader.IsViewMultiplied(SystemName)); } catch (Exception e) { LogEvent(string.Format("IsViewMultiplied() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(false); }
/// <summary> /// Процедура возвращает объект ADODB.Recordset, предоставляющий информацию об объектах View, доступных в конфигурационном хранилище системы ECR /// и являющихся наследниками объекта Entity с заданным системным именем; /// </summary> /// <param name="EntityName">Системное имя объекта Entity, являющегося родителем для объектов View</param> /// <param name="Enabled">Признак доступности объектов View (true/false)</param> /// <returns>ADODB.Recordset. Набор данных объектов View</returns> public ADODB.Recordset GetViewListByEntity(string EntityName, bool Enabled) { try { var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); return(DataSetConverter.DataSetConverter.ConvertToADODBRecordset(_reader.GetViewListByEntity(EntityName, Enabled))); } catch (Exception e) { LogEvent(string.Format("GetViewListByEntity() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(null); }
/// <summary> /// Процедура возвращает объект ADODB.Recordset, предоставляющий информацию о наборе всех объектов Binding, доступных в системе ECR; /// </summary> /// <returns>ADODB.Recordset. Набор данных объектов Binding</returns> public ADODB.Recordset GetBindingsList() { try { // Define ECRManagedDataReader class instance from external ECRManagedAssemblies class library var _reader = new ECRManagedDataReader(_dataSourceServerName, _connectionTimeout, _commandTimeout, _DEBUG); // This construct using DataSetConverter class from external DataSetConverter class library return(DataSetConverter.DataSetConverter.ConvertToADODBRecordset(_reader.GetBindingsList())); } catch (Exception e) { LogEvent(string.Format("GetBindingsList() call procedure error. Instance ID: '{0}', exception: '{1}'", _INSTANCE_ID, e.Message), "ERROR"); } return(null); }
/// <summary> /// Обновление сводной таблицы ecr.ItemsSummary базы данных ECR_Config /// </summary> /// <param name="ItemKey">Товарный ключ позиции</param> /// <param name="ItemNumber">Номер позиции</param> /// <param name="EntityName">Идентификатор типа контента</param> /// <param name="OperationType">Тип операции (I/U/D/C)</param> public void UpdateItemSummary(string ItemKey, int?ItemNumber, string EntityName, string OperationType) { var reader = new ECRManagedDataReader(_baseServerName, _connectionTimeout, _commandTimeout); using (var conn = new SqlConnection { ConnectionString = _connectionString }) { conn.Open(); try { var cmd = new SqlCommand { CommandType = CommandType.StoredProcedure, CommandTimeout = Convert.ToInt32(_commandTimeout), CommandText = "[ecr].[UpdateItemSummary]", Connection = conn }; cmd.Parameters.AddWithValue("@DisplayAlias", reader.GetEntityAliasByName(EntityName)); cmd.Parameters.AddWithValue("@ItemKey", ItemKey); if (ItemNumber != null) { if (ItemNumber > 0) { cmd.Parameters.AddWithValue("@ItemNumber", ItemNumber); } else { cmd.Parameters.AddWithValue("@ItemNumber", DBNull.Value); } } else { cmd.Parameters.AddWithValue("@ItemNumber", DBNull.Value); } cmd.Parameters.AddWithValue("@OperationType", OperationType); cmd.CommandTimeout = DEFAULT_COMMAND_TIMEOUT; cmd.ExecuteNonQuery(); } finally { conn.Close(); } } }
/// <summary> /// Метод запускает задание обработки и загрузки данных в хранилище ECR /// </summary> public void Execute() { _log.Info(string.Format("Запуск задания... Key: '{0}', ItemType: '{1}', , Source: '{2}', Mask: '{3}', Save Originals: {4}", Key, ItemType, Source, Mask, SaveOriginals)); // Проверка на доступность объекта if (!Enabled) { // Если объект недоступен, то пишем в лог и выходим _log.Warn(string.Format("Задание: {0} заблокировано. Задание неактивно либо доступ запрещен", Key)); return; } Debug("Определение папки для сброса файлов с ошибками..."); var _pathErrors = ConfigurationManager.AppSettings.Get("ECR.ProcessingManager.PathErrors"); if (_pathErrors.Length > 0) { if (!Directory.Exists(_pathErrors)) { _log.Error(string.Format("Ошибка доступа к папке: ' {0}'", _pathErrors)); return; } } #region Инициализация счетчиков var _processed = 0; var _success = 0; var _errors = 0; var _warnings = 0; #endregion Debug("Получение списка файлов..."); // Резервируем файлы для обработки переименовывая их <file_name>.ecr$ var di = new DirectoryInfo(Source); // Проверяем есть ли зарезервированные но не обработаные файлы var _files = di.GetFiles("*.ecr$"); // Если файлов нет, забираем новые if (_files.Length == 0) { Debug("Получение списка новых файлов..."); // Формируем маску файла в виде *[_*].* var _inputMask = Mask.Replace("[ext]", "*"); _inputMask = _inputMask.Replace(_keyTokens[0], "*"); _inputMask = _inputMask.Replace(_keyTokens[1], "*"); _inputMask = _inputMask.Replace(_numberToken, "*"); // Резервируем файлы foreach (var fileInfo in di.GetFiles(_inputMask)) { fileInfo.MoveTo(fileInfo.FullName + ".ecr$"); } // Получаем зарезервированные файлы _files = di.GetFiles("*.ecr$"); } // Объявление интерфейсной переменной основного объекта проверки и обработки данных IECRProcessor _processor; // Тип контейнера определяет какой тип объекта преобразований создавать в интерфейсной переменной switch (ContainerType) { case _ctGraphical: _processor = new GraphicsProcessor(ContainerId); break; case _ctTextDefault: _processor = new TextProcessor(ContainerId); break; default: _log.Error(string.Format("Неизвестный тип контейнера данных: '{0}'", ContainerType)); return; } // Определяем объект ECRManagedDataReader Debug("Определение объекта ECRManagedDataReader..."); var _ecrDataReader = new ECRManagedDataReader(ConfigurationManager.AppSettings.Get("ECR_Config.BaseServerName"), Convert.ToInt32(ConfigurationManager.AppSettings.Get("ECR_Config.ConnectionTimeout")), Convert.ToInt32(ConfigurationManager.AppSettings.Get("ECR_Config.CommandTimeout")), DebugMode); var _ecrDataWriter = new ECRManagedDataWriter(ConfigurationManager.AppSettings.Get("ECR_Config.BaseServerName"), Convert.ToInt32(ConfigurationManager.AppSettings.Get("ECR_Config.ConnectionTimeout")), Convert.ToInt32(ConfigurationManager.AppSettings.Get("ECR_Config.CommandTimeout")), DebugMode); // Определяем сущность из конфигурационной базы ECR Debug("Определение свойств обрабатываемой сущности..."); var _dsEntity = _ecrDataReader.GetEntity(ItemType); // Определяем список доступных представлений-наследников для сущности с системным именем ItemType Debug("Определение списка потомков сущности..."); var _dsChildViews = _ecrDataReader.GetViewListByEntity(ItemType, true); Debug("Обработка файлов..."); foreach (var _file in _files) { try { Debug(string.Format("Обрабатывается файл: '{0}'...", _file.FullName)); _processed++; // Определение ItemKey, ItemNumber Debug("Определение параметров ключей..."); var itemKey = _file.Name; itemKey = itemKey.Replace(_file.Extension, string.Empty); var _fi = new FileInfo(itemKey); itemKey = itemKey.Replace(_fi.Extension, string.Empty); var index = itemKey.IndexOf("_"); int?itemNumber = null; if (Convert.ToBoolean(_dsEntity.Tables["EntityData"].Rows[0]["IsMultiplied"])) // if IsMultiplied { if (index > -1) { // По правилам наименования файлов если контент множественный, то первый номер проходит без "_*"! itemNumber = Convert.ToInt32(itemKey.Substring(index + 1)) + 1; itemKey = itemKey.Replace(string.Format("_{0}", itemNumber - 1), string.Empty); } else { itemNumber = 1; } } else { if (index > -1) { throw new Exception( string.Format("Некорректное имя файла для немножественной сущности. Файл: '{0}', сущность: '{1}'", _file.FullName, ItemType)); } } // Убираем нечисловые символы из itemKey var _itemKey = string.Empty; foreach (var _c in itemKey) { for (var l = 0; l < 10; l++) { if ((int)_c == (int)((l.ToString().ToCharArray())[0])) { _itemKey = _itemKey + _c; break; } } } itemKey = _itemKey; Debug(string.Format("Передача данных, ItemKey: '{0}', ItemNumber: {1}", itemKey, itemNumber)); // В зависимости от типа контейнера преобразований получаем данные в Unicode или в Base64 и применяем преобразования Debug(string.Format("Чтение данных из файла: '{0}'", _file.FullName)); object _buffer = null; #region Формирование данных из файла // Тип контейнера определяет как считывать данные из файла switch (ContainerType) { case _ctGraphical: using (var _fs = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read)) { _buffer = new byte[(int)_fs.Length]; try { _fs.Read(_buffer as byte[], 0, (int)_fs.Length); } finally { _fs.Close(); } } break; case _ctTextDefault: var _sr = new StreamReader(_file.FullName, Encoding.Default); _buffer = new char[(int)_sr.BaseStream.Length]; try { _sr.Read(_buffer as char[], 0, (int)_sr.BaseStream.Length); } finally { _sr.Close(); } break; } #endregion // Загрузка данных в основной процессинговый объект. Debug(string.Format("Загрузка данных в процессор ECR. Файл: '{0}'", _file.FullName)); var _error = string.Empty; string _check_params; if (_dsEntity.Tables["EntityData"].Rows[0]["Params"] == DBNull.Value) { _check_params = null; } else { _check_params = (string)_dsEntity.Tables["EntityData"].Rows[0]["Params"]; } // Загрузка определяется дефолтными преобразованиями данных (которых может и не быть), заданными в контейнере. // Загрузка осуществляет также проверку данных на соответствие стандартам, заданным в контейнере. if (!_processor.LoadObject(_buffer, _checkProperties, _defaultProcessing, _check_params, ref _error)) { // Возврат файла в папку обработки ошибок // TODO: сделать проверку на отсутствие сети! // TODO: сделать отдельную нотификацию через log4net (SMTPAppender) _log.Warn(string.Format("Проверка свойств не пройдена! Описание ошибки: '{0}'. Файл: '{1}'", _error, _file.FullName)); if (_pathErrors.Length > 0) { Debug(string.Format("Копирование файла в папку обработки ошибок: '{0}'", _file.Name)); // При возврате файла отрезаем расширение ".ecr$" _file.CopyTo(_pathErrors + ItemType + "\\" + (_file.Name).Replace(".ecr$", string.Empty), true); Debug(string.Format("Файл скопирован в папку обработки ошибок: '{0}'", _file.Name)); } _warnings++; } else { // TODO: после заливки всех данных реализовать здесь функционал проверки наличия сущности в хранилище ECR С использованием ItemsSummary // TODO: опционально по значению параметра overwrite осуществлять проверку и в случае overwite=false и сущность уже существует копировать файл в папку global if (!Overwrite) { } // Получаем базовые данные и определяем тип операции byte[] _base = _processor.GetBase(); var _operation = _base.Length > 0 ? "I" : "D"; // Запись информации в сводную таблицу ECR_Config.ecr.ItemsSummary для сбора статистики // TODO: здесь хардкод по операции "I" (insert) вставки данных в таблицу ItemsSummary // TODO: Впоследствии нужно добавить процедуру ECR_Config.ecr.CheckItemExists // TODO: и разрулить всю логику от ее возвращаемого значения, а также проверять значение на null (~ операции очистки - "C") _ecrDataWriter.UpdateItemSummary(itemKey, itemNumber, ItemType, _operation); // Загрузка базового представления (оригинала) в базу ECR_Storage. // Флаг SaveOriginals не является интерфейсным и не фигурирует в настройках сущностей в базе ECR_Config. // Это "чисто конфигурационная" вещь, созданная для удобства промежуточных заливок данных. if (SaveOriginals) { Debug("Передача данных оригинала в хранилище ECR. Файл: '" + _file.FullName + "'"); _ecrDataWriter.TransferEntity(itemKey, itemNumber, _base, ItemType); Debug(string.Format("Данные оригинала переданы в хранилище ECR. Файл: '{0}'", _file.FullName)); } // Проверка наличия записей о генерации потомков Debug(string.Format("Передача данных представлений в хранилище ECR. Файл: '{0}'", _file.FullName)); if (_dsChildViews.Tables["ViewList"].Rows.Count > 0) { // Создание и загрузка в базу ECR_Storage представлений-потомков в цикле по исходным данным из ECR_Config var _etr = _dsChildViews.Tables["ViewList"].Rows.GetEnumerator(); while (_etr.MoveNext()) { var _row = (DataRow)_etr.Current; Debug(string.Format("Передача данных в хранилище ECR. Представление: '{0}'. Файл: '{1}'", _row["SystemName"], _file.FullName)); _ecrDataWriter.TransferView( itemKey, itemNumber, _operation == "D" ? _base : _processor.CreateView(_row["SystemName"].ToString(), _row["Params"].ToString()), _row["SystemName"].ToString() ); Debug(string.Format("Данные представления переданы в хранилище ECR. Представление: '{0}'. Файл: '{1}'", _row["SystemName"], _file.FullName)); } } _log.Info(string.Format("Файл успешно обработан: '{0}'", _file.FullName)); // Если задан путь для дополнительного копирования, то бэкапим исходный файл. // Данные предыдущих бэкапов перезатираются. if (BackupTo.Length > 0) { Debug(string.Format("Копирование файла '{0}' в папку: '{1}'...", _file.Name.Replace("ecr$", string.Empty), BackupTo + ItemType + "\\")); _file.CopyTo(BackupTo + ItemType + "\\" + _file.Name.Replace("ecr$", string.Empty), true); Debug(string.Format("Файл '{0}' скопирован в папку: '{1}'", _file.Name.Replace("ecr$", string.Empty), BackupTo + ItemType + "\\")); } _success++; } } catch (Exception e) { _log.Error(string.Format("Ошибка при обработке файла: '{0}'", _file.FullName), e); if (_pathErrors.Length > 0) { Debug(string.Format("Копирование файла в папку обработки ошибок: '{0}'", _file.Name)); // При возврате файла отрезаем расширение ".ecr$" _file.CopyTo(_pathErrors + ItemType + "\\" + (_file.Name).Replace(".ecr$", string.Empty), true); Debug(string.Format("Файл скопирован в папку обработки ошибок: '{0}'", _file.Name)); } _errors++; } finally { // Удаляем отработанный файл Debug(string.Format("Удаление файла: '{0}'", _file.FullName)); _file.Delete(); Debug(string.Format("Файл удален: '{0}'", _file.FullName)); } } // foreach _log.Info(string.Format("Обработано {0} файлов, {1} - успешно, {2} - с ошибками, {3} - с предупреждениями.", _processed, _success, _errors, _warnings)); }