Перейти к содержанию

Изменение поля карточки через низкоуровневое API

Изменение поля карточки через низкоуровневое API

Рассмотрим ситуацию, когда требуется прочитать и изменить секции карточки в условиях высокой нагрузки. Например, разрабатывается интеграционный сервис, который может вызываться сотни раз в секунду для разных карточек. Только при наличии очень высоких требований к производительности можно использовать низкоуровневое API карточек из пространства имён Tessa.Cards.ComponentModel.

Note

В подавляющем большинстве случаев достаточно использовать высокоуровневое API ICardRepository. Для оптимизации же можно отключить расширения, т.е. получить объект из Unity с указанием имени CardRepositoryNames.Default. При этом не будут проверяться права доступа к карточке, не будет записи в лог аудита и других действий, выполняемых в расширениях платформы, типового решения или расширениях для вашего проекта.

В классе расширения или в классе веб-сервиса, в котором нужно прочитать карточку через низкоуровневое API, укажем поля, которые заполним в конструкторе из Unity:

private readonly ISession session;

private readonly ICardMetadata cardMetadata;

private readonly ICardTransactionStrategy transactionStrategy;

private readonly ICardGetStrategy getStrategy;

private readonly ICardStoreExecutionStrategy storeExecutionStrategy;

Также укажем статическое поле класса для объекта логирования:

private static readonly Logger logger = LogManager.GetCurrentClassLogger();

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

Guid cardID = ...; var validationResult = new ValidationResultBuilder();

// выполняемся в блокировке на запись карточки, чтобы параллельно никто не мог загружать и изменять карточку bool success = this.transactionStrategy .ExecuteInWriterLock( cardID, CardComponentHelper.DoNotCheckVersion, validationResult, p => { // загружаем системную информацию из таблицы Instances CardGetContext getContext = this.getStrategy .TryLoadCardInstance( cardID, p.DbScope.Db, cardMetadata, validationResult);

if (getContext == null) { p.ReportError = true; return; }

// нужны только секции DocumentCommonInfo и OutgoingRefDocs, исключаем остальные // в getContext.CardMetadata.Sections лежат только секции загруженного типа карточки getContext.SectionsToExclude.AddRange( getContext.CardMetadata.Sections .Where(x => x.Name != "DocumentCommonInfo" && x.Name != "OutgoingRefDocs") .Select(x => x.ID) .ToArray());

// загружаем все секции карточки, кроме тех, которые мы исключили if (!this.getStrategy.LoadSections(getContext)) { p.ReportError = true; return; }

// изменяем карточку: здесь может быть любая логика, связанная с изменением полей, // используя DynamicEntries или Fields для строковых секций или строк в коллекционных секциях // (для строк также нужно указать свойство State) Card card = getContext.Card; card.DynamicEntries.DocumentCommonInfo.FullNumber = "Дпр-00004";

// сохраняем карточку card.RemoveAllButChanged();

var storeContext = new CardStoreContext( card, DateTime.UtcNow, // дата и время изменения карточки this.session, this.cardMetadata, new ValidationResultBuilder(), p.DbScope.Executor, p.DbScope.BuilderFactory);

this.storeExecutionStrategy.StoreSections(storeContext);

// если есть ошибки при сохранении, то нужно откатить транзакцию validationResult.Add(storeContext.ValidationResult); if (!storeContext.ValidationResult.IsSuccessful()) { // откатываем транзакцию p.ReportError = true; } });

if (!success) { // логируем ошибки logger.LogResult(validationResult.Build()); }

Back to top