Ошибка при генерации кода для свойства update order недоступен в целевой платформе

Содержание

При добавлении/изменении большого количества записей (10³ и выше), производительность Entity Framework оставляет желать лучшего. Причиной этому являются как архитектурные особенности самого фреймворка, так и неоптимальный генерируемый SQL. Забегая вперед — сохранение данных в обход контекста сокращает время выполнения на порядки.

Содержание статьи:
1. Insert/Update стандартными средствами Entity Framework
2. Поиск решения проблемы
3. Интеграция Entity Framework и SqlBulkCopy
4. Продвинутая вставка с использованием MERGE
5. Сравнение производительности
6. Выводы

1. Insert/Update стандартными средствами Entity Framework

Начнем с Insert. Стандартным способом добавления новых записей в БД является добавление в контекст с последующим сохранением:

Каждый вызов метода Add приводит к дорогостоящему в плане выполнения вызову внутреннего алгоритма DetectChanges. Данный алгоритм сканирует все сущности в контексте и сравнивает текущее значение каждого свойства с исходным значением, хранимым в контексте, обновляет связи между сущностями и т. п. Известным способом поднятия производительности, актуальным до выхода EF 6, является отключение DetectChanges на время добавления сущностей в контекст:

Также рекомендуется не держать в контексте десятки тысяч объектов и сохранять данные блоками, сохраняя контекст и создавая новый каждые N объектов, например, как тут. Наконец, в EF 6 появился оптимизированный метод AddRange, поднимающий производительность до уровня связки Add+AutoDetectChangesEnabled:

К сожалению, перечисленные подходы не решают основной проблемы, а именно: при сохранении данных в БД, на каждую новую запись генерируется отдельный INSERT запрос!

С Update ситуация аналогичная. Следующий код:

приведет к выполнению отдельного SQL-запроса на каждый измененный объект:

В простейших случаях, может помочь EntityFramework. Extended:

Данный код выполнится в обход контекста и сгенерирует 1 SQL-запрос. Более подробно о скорости EF и работе с этой библиотекой в статье за авторством tp7. Очевидно, что решение не универсальное и годится только для записи во все целевые строки одного и того же значения.

2. Поиск решения проблемы

Испытывая стойкое отвращение к написанию «велосипедов», я в первую очередь поискал best-practices для множественной вставки с помощью EF. Казалось бы, типовая задача — но подходящего решения «из коробки» найти не удалось. В то же время, SQL Server предлагает ряд техник быстрой вставки данных, таких как утилита bcp и класс SqlBulkCopy. О последнем и пойдет речь ниже.

EntityFramework. BulkInsert
На поверку оказавшийся нерабочим. При изучении Issues я наткнулся на дискуссию с участием… небезызвестной Julie Lerman, описывающую проблему, аналогичную моей и оставшуюся без ответа авторов проекта.

EntityFramework. Utilities
Живой проект, активное сообщество. Нет поддержки Database First, но обещают добавить.

3. Интеграция Entity Framework и SqlBulkCopy

Попробуем сделать всё сами. В простейшем случае, вставка данных из коллекции объектов с помощью SqlBulkCopy выглядит следующим образом:

Сама по себе задача реализовать IDataReader на основе коллекции объектов тривиальна, поэтому я ограничусь ссылкой и перейду к описанию способов обработки ошибок при вставке с использованием SqlBulkCopy. По умолчанию, вставка данных производится в своей собственной транзакции. При возникновении исключения выбрасывается SqlException и происходит rollback, т. е. данные в БД не будут записаны вообще. А «родные» сообщения об ошибках данного класса иначе как неинформативными не назовешь. Например, что может содержать SqlException. AdditionalInformation:

К сожалению, SqlBulkCopy зачастую не предоставляет информацию, позволяющую однозначно определить строку/сущность, вызвавшие ошибку. Еще одна неприятная особенность — при попытке вставить дубликат записи по первичному ключу, SqlBulkCopy выбросит исключение и завершит работу, не предоставляя возможности обработать ситуацию и продолжить выполнение.

Маппинг
В случае корректно сгенерированных сущностей и БД становятся неактуальными проверки на соответствие типов, или длину поля в таблице, как тут. Полезней разобраться с маппингом колонок, выполняемым через свойство SqlBulkCopy. ColumnMappings:

Что дает возможность вручную провести маппинг между классом-источником и целевой таблицей.

Использование свойства SqlBulkCopy. BatchSize и класса SqlBulkCopyOptions

SqlBulkCopy. BatchSize:

BatchSize Количество строк в каждом пакете. В конце каждого пакета серверу отправляется количество содержащихся в нем строк.

SqlBulkCopyOptions — перечисление:

Имя члена Описание
CheckConstraints Проверять ограничения при вставке данных. По умолчанию ограничения не проверяются.
Default Использовать значения по умолчанию для всех параметров.
FireTriggers Когда задана эта установка, сервер вызывает триггеры вставки для строк, вставляемых в базу данных.
KeepIdentity Сохранять идентификационные значения источника. Когда эта установка не задана, идентификационные значения присваиваются таблицей назначения.
KeepNulls Сохранять значения NULL в таблице назначения независимо от параметров значений по умолчанию. Когда эта установка не задана, значения null, где возможно, заменяются значениями по умолчанию.
TableLock Получать блокировку массового обновления на все время выполнения операции массового копирования данных. Когда эта установка не задана, используется блокировка строк.
UseInternalTransaction Когда эта установка задана, каждая операция массового копирования данных выполняется в транзакции. Если задать эту установку и предоставить конструктору объект SqlTransaction, будет выброшено исключение ArgumentException.

Мы можем опционально включить проверку триггеров и ограничений на стороне БД (по умолчанию выключена). При указании BatchSize и UseInternalTransaction, данные будут отправляться на сервер блоками в отдельных транзакциях. Таким образом, все успешные блоки до первого ошибочного, будут сохранены в БД.

4. Продвинутая вставка с использованием MERGE

Временная таблица
Необходимо создать таблицу в БД, полностью повторяющую схему таблицы для вставки данных. Создавать копии вручную — худший вариант из возможных, так как вся дальнейшая работа по сравнению и синхронизации схем таблиц также ляжет на ваши плечи. Надежнее копировать схему программно и непосредственно перед вставкой. Например, с использованием SQL Server Management Objects (SMO):

Стоит обратить внимание на класс ScriptingOptions, содержащий несколько десятков параметров для тонкой настройки генерируемого SQL. Полученный StringCollection развернем в String. К сожалению, лучшего решения, чем заменить в скрипте имя исходной таблицы на имя временной а-ля String. Replace(«Order», «Order_TEMP»), я не нашел. Буду благодарен за подсказку красивого решения по созданию копии таблицы в пределах одной БД. Выполним готовый скрипт любым удобным способом. Копия таблицы создана!

Другой вариант — использовать Database. ExecuteWithResults.

Копирование данных из временной таблицы в целевую
Осталось выполнить на стороне SQL Server инструкцию MERGE, сравнивающую содержимое временной и целевой таблиц и выполняющую апдейт или вставку (если необходимо). К примеру, для таблицы [Order] код может выглядеть следующим образом:
схема таблицы

Данный SQL-запрос сравнивает записи из временной таблицы [Order_TEMP] с записями из целевой таблицы [Order], и выполняет Update, если найдена запись с аналогичным значением в поле Id, либо Insert, если такой записи не найдено. Выполним код любым удобным способом, и готово! Не забываем очистить/удалить временную таблицу по вкусу.

5. Сравнение производительности

Среда выполнения: Visual Studio 2013, Entity Framework 6.1.1 (Database First), SQL Server 2012. Для тестирования использовалась таблица [Order] (схема таблицы приведена выше). Были проведены измерения времени выполнения для рассматриваемых в статье подходов к сохранению данных в БД, результаты представлены в ниже (время указано в секундах):

Insert

Способ фиксации изменений в базе данных Количество записей
1000 10000 100000
Add + SaveChanges 7,3 101 6344
Add + (AutoDetectChangesEnabled=false) + SaveChanges 6,5 64 801
Add + отдельный контекст + SaveChanges 8,4 77 953
AddRange + SaveChanges 7,2 64 711
SqlBulkCopy 0,01 0,07 0,42

Ого! Если использовать метод Add для добавления в контекст и SaveChanges для сохранения, сохранение 100000 записей в БД займет почти 2 часа! В то время, как SqlBulkCopy на эту же задачу тратит менее секунды!

Update

Способ фиксации изменений в базе данных Количество записей
1000 10000 100000
SaveChanges 6,2 60 590
SqlBulkCopy + MERGE 0,04 0,2 1,5

Вновь SqlBulkCopy вне конкуренции. Исходный код тестового приложения доступен на GitHub.

Выводы

В случае работы с контекстом, содержащим большое количество объектов (10³ и выше), отказ от инфраструктуры Entity Framework (добавление в контекст + сохранение контекста) и переход на SqlBulkCopy для записи в БД может обеспечить прирост производительности в десятки, а то и сотни раз. Однако, по моему мнению, использовать связку EF+SqlBulkCopy повсеместно — явный признак того, что с архитектурой вашего приложения что-то не так. Рассмотренный в статье подход следует рассматривать как простое средство для ускорения производительности в узких местах уже написанной системы, если менять архитектуру/технологию по каким-либо причинам затруднительно. Любой разработчик, использующий Entity Framework, должен знать сильные и слабые стороны этого инструмента. Успехов!

Записки IT специалиста

Типовые ошибки установки сервера 1С:Предприятие и PostgreSQL на платформе Linux.

1cv8-pgsql-error-000.jpgСвязка сервера 1С:Предприятие и PostgreSQL вторая по популярности среди установок 1С и самое используемое решение на платформе Linux. В отличии внедрений на базе Windows и MSSQL, где трудно сделать так, чтобы не заработало, внедрения на базе Linux таят множество подводных камней для неопытного администратора. Часто бывает так, что вроде бы все сделано правильно, но ошибка следует за ошибкой. Сегодня мы рассмотрим самые типовые из них.

Общая информация

Перед тем, как начинать искать ошибки установки и, вообще, приступать к внедрению серверной версии 1С:Предприятия было бы неплохо освежить представление как это работает:

В небольших внедрениях сервер 1С и сервер СУБД обычно совмещают на одном физическом сервере, что немного сужает круг возможных ошибок. В нашем случае будет рассматриваться ситуация, когда сервера разнесены по разным машинам. В нашей тестовой лаборатории мы развернули следующую схему:

1cv8-pgsql-error-002.jpg

В нашем распоряжении имеются два сервера под управлением Ubuntu 12.04 x64, на одном из них установлен сервер 1С:Предприятие версии 8.3, на другом PostgreSQL 9.04 от Ethersoft, а также клиент под управлением Windows. Напоминаем, что клиент работает только с сервером 1С, который, в свою очередь, формирует необходимые запросы к серверу СУБД. Никаких запросов от клиента к серверу управления базами данных не происходит.

Сервер баз данных не обнаружен
ВАЖНО: пользователь «postgres» не прошёл проверку подлинности (Ident)

1cv8-pgsql-error-003.jpg

Данная ошибка возникает при разнесении серверов по разным ПК из-за неправильно настроеной проверки подлинности в локальной сети. Для устранения откройте /var/lib/pgsql/data/pg_hba. conf, найдите строку:

и приведите ее к виду:

Сервер баз данных не обнаружен
could not translate host name «NAME» to address: Temporary failure in name resolution

1cv8-pgsql-error-004.jpg

На первый взгляд ошибка понятна: клиент не может разрешить имя сервера СУБД, типичная ошибка для небольших сетей, где отсутствует локальный DNS-сервер. В качестве решения добавляют запись в файл hosts на клиенте, что не дает никакого результата.

А теперь вспоминаем, о чем было сказано несколько раньше. Клиентом сервера СУБД является сервер 1С, но никак не клиентский ПК, следовательно запись нужно добавлять на сервере 1С:Предприятие в файл /etc/hosts на платформе Linux или в C:\Windows\System32\drivers\etc\hosts на платформе Windows.

1cv8-pgsql-error-005.jpg

Аналогичная ошибка будет возникать, если вы забыли добавить запись типа A для сервера СУБД на локальном DNS-сервере.

Ошибка при выполнении операции с информационной базой
server_addr=NAME descr=11001(0x00002AF9): Этот хост неизвестен.

1cv8-pgsql-error-006.jpg

Как и прошлая, эта ошибка связана с неправильным разрешением клиентом имени сервера. На этот раз именно клиентским ПК. В качестве решения добавляем в файл /etc/hosts на платформе Linux или в C:\Windows\System32\drivers\etc\hosts на платформе Windows запись вида:

где указываете адрес и имя вашего сервера 1С:Предприятия. В случае использования локального DNS следует добавить A-запись для сервера 1С.

Ошибка СУБД: DATABASE не пригоден для использования

1cv8-pgsql-error-007.jpg

Гораздо более серьезная ошибка, которая говорит о том, что вы установили несовместимую с 1С:Предприятие версию PostgreSQL или допустили грубые ошибки при установке, например не установили все необходимые зависимости, в частности библиотеку libICU.

Если вы имеете достаточный опыт администрирования Linux систем, то можете попробовать доустановить необходимые библиотеки и заново инициализировать кластер СУБД. В противном случае PostgreSQL лучше переустановить, не забыв удалить содержимое папки /var/lib/pgsql.

Также данная ошибка может возникать при использовании сборок 9.1.x и 9.2.x Postgre@Etersoft, подробности смотрите ниже.

Ошибка СУБД:
ERROR: could not load library «/usr/lib/x86_64-linux-gnu/postgresql/fasttrun. so»

Ошибка СУБД
ERROR: type «mvarchar» does not exist at character 31

1cv8-pgsql-error-009.jpg

Возникает если база данных была создана без помощи системы 1С:Предприятия. Помните, для работы с 1С базы данных следует создавать только с использованием инструментов платформы 1С: через консоль Администрирование серверов 1С Предприятия

1cv8-pgsql-error-010.jpg

или через средство запуска 1С.

1cv8-pgsql-error-011.jpg

Сервер баз данных не обнаружен
ВАЖНО: пользователь «postgres» не прошёл проверку подлинности (по паролю)

1cv8-pgsql-error-012.jpg

Очень простая ошибка. Неправильно указан пароль суперпользователя СУБД postgres. Вариантов решения два: вспомнить пароль или изменить его. Во втором случае вам нужно будет изменить пароль в свойствах всех существующих информационных баз через оснастку Администрирование серверов 1С Предприятия.

Сервер баз данных не обнаружен
FATAL: database «NAME» does not exist

Как исправить ошибку при генерации RSA ключа для ЕГАИС?

Эльба

При генерации RSA ключа (транспортного ключа) в личном кабинете ЕГАИС алкоголь могут возникать ошибки. Разобраться в этих ошибках непросто специалисту, не говоря уже о рядовом пользователе.

Попробуем разобрать типовые ошибки, которые возникают при генерации транспортных RSA ключей ЕГАИС.

Почему возникает ошибка при генерации ключа ЕГАИС?

В основном ошибки при генерации связаны с некорректными настройками компьютера.

Общие рекомендации для успешной генерации транспортного RSA ключа ЕГАИС

Для успешной генерации транспортных ключей на сайте ЕГАИС необходимо соблюсти некоторые требования и рекомендации:

Ошибка при генерации RSA ключа «Выберете устройство чтения смарт карт. «

Если при генерации ключа ЕГАИС вместо окна запроса пин-кода Вы увидели окно «Выберете устройство чтения смарт карт» или «Обнаружена смарт-карта, но она не может использоваться для текущей операции. » или «Смарт-карта не может выполнить запрошенную операцию либо операция требует другой смарт-карты», значит нужно скорректировать настройки компьютера.

ошибка при генерации rsa ключа егаис вставьте смарт-карту

Такая ошибка возникает из-за того, что настройки вашего компьютера не позволяют сформировать ключи, необходимые для работы УТМ ЕГАИС.

Если Вы используете носитель Рутокен ЭЦП, то вам необходимо сделать следующее:

настройка криптопровайдера рутокен эцп
настройка криптопровайдера рутокен эцп

Пробуйте сгенерировать транспортный ключ ЕГАИС еще раз.

В крайне редких случаях, если генерация ключа не проходит, помогает утилита восстановления работоспособности Рутокен (позволяет правильно определить драйвера носителя в системе).

Все должно получиться!

Ошибка в методе createCertificateRequest Error: CKR_PNI_INCORRECT

В этой ошибке прямым текстом, правда по иностранному, написано, что неверно введен пин-код.

ошибка пин кода

Проверьте правильность ввода пин-кодов. Если на вашем носителе установлен пин-код по умолчанию. и Вы его не помните, то напоминаем:

Если не подходят стандартные пин-коды и пин-код, который установили Вы, то скорее всего носитель заблокировался. Для разблокировки носителя обратитесь к тому, у кого получали ключи, должны помочь.

Ошибка в методе createCertificateRequest Error: CKR_ATTRIBUTE_TYPE_INVALID

Такая ошибка была нами зафиксирована при использовании ключа JaCarta SE.

ошибка при получении RSA ключа

Для исправления ошибки необходимо инициализировать раздел PKI на носителе. Для этого откройте Единый клиент JaCarta желательно включить интерфейс Администратора (снизу слева кнопка «Переключиться в режим администрирования»). Перейдите вверху во вкладку PKI и нажмите «Инициализировать». При запросе пин-кода введите пин-код Администратора 00000000, пин-код Пользователя 11111111.

После успешной инициализации попробуйте снова сгенерировать транспортный ключ.

Также не забывайте о том, что для нормальной работы вашего защищенного носителя для ЕГАИС должен быть установлен свежий драйвер ключа!

Решения самых популярных проблем с ЕГАИС Вы можете найти в нашем Telegram канале «ЕГАИС простыми словами» (@egais_is_easy ).

Источники:

https://habr. com/ru/post/251397/

https://interface31.ru/tech_it/2014/05/tipovye-oshibki-ustanovki-servera-1s-i-postgresql-na-platforme-linux. html

https://avitek. ru/info/articles/kak-ispravit-oshibku-pri-generatsii-rsa-klyucha-dlya-egais/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: