Уникальное поле

Добрый день
Подскажите, пожалуйста, как лучше сделать логику заполнения поля в карточке КЕ:
нужно, чтобы поле содержало строго 10 символов (или цифр?), при заполнении этого поля должна быть проверка на уникальность (значения этого поля не должны повторяться).
Примеры заполнения поля: 0000000001, 0000000002, ..., 0000000011, ....

Заранее спасибо

Нравится

54 комментария

Здравствуйте, Татьяна!

С примером настройки автонумерации в 5.x вы можете ознакомиться в этом посте - ссылка.

Подскажите, пожалуйста, как на с# сделать проверку поля, чтобы в нем было не более 10-ти символов?

Проверку можно сделать на нажатии ОК в карточке. Как здесь, только без вопроса.

понятно. А на С# как написать, как подсчитать кол-во символов?

А если надо, чтобы первые две цифры в значении поля были 69, как можно написать условие проверки на С#?

В MSDN описана работа со строками в C#, смотрите там.

Решила сделать сист.настройку "Текущий номер КЕ" (числовое, не кешируется. Наименование - KELastNumber), без маски номера.

В дизайнере процессов Конф.единица делаю:

Сохранила, опубликовала без ошибок.
При создании новой КЕ - в поле ITNumber (в котором и должен подставляться текущий номер) вообще нет никаких значений. В чем моя ошибка, подскажите, пожалуйста.

// не поняла, должна ли в схеме "Сгенерировать номер по порядку" указываться моя новая системная настройка KELastNumber и где именно указывается связь этой настройки с полем ITNumber в карточке КЕ

Татьяна, смотрите, как сделано в других разделах и делайте всё аналогично.
Если не хотите аналогично, изучайте схему «Сгенерировать номер по порядку», переделывайте её по-своему.
По стандартной логике, название системных настроек должно быть совпадающим с названием схемы плюс «LastNumber» и «CodeMask» соответственно.

Я хочу воспользоваться станд.логикой, смотрю, как сделано в других разделах. Изменила название своей новой сист.настройки ConfigurationItemLastNumber (чтобы соответствовала станд.логике), добавила сист.настройку маска номера КЕ (ConfigurationItemCodeMask). Все равно не работает, ничего в поле ITNumber в карточке КЕ не записывает. Подскажите, пожалуйста, на что еще обратить внимание?

нужно ли чистить Redis?

Да, попробуйте очистить Redis и профиль.

Если после этого функциональность не заработает, следовательно ошибка в реализации и её следует искать в программном коде. В таком случае, нужно будет отладиться.

Добрый день.
Решили не использовать маску номера, а сделать проверку на уникальность: т.е. значение цифрового поля не должно повторяться (не обязательно следующее должно быть больше на 1). Подскажите, пожалуйста, как это сделать? Заранее спасибо

Такую функциональность вообще можно реализовать на уровне СУБД.

1. В bpm'online создайте системную настройку, в которой будет храниться номер последней созданной записи.
2. Потом на уровне СУБД реализовать триггер, который будет срабатывать на добавление новой записи. В этом триггере нужно считывать номер из системной настройки, вычислять значение нового номера = номер из системной настройки + 1, устаналивать его в нужное поле в таблицу и обновлять значение системной настройки новым номером.

мне не нужно хранить номер последней записи, т.к. к ней не нужно добавлять +1.
Мне нужно сделать проверку на уникальность, т.е. новая запись в этом поле должна быть не равна имеющимся.

Татьяна, чтобы сделать проверку на уникальность, можете на нажатии OK в обработчике сделать запуск Select, который ищет в разделе записи с таким же значением. И если находит таковых больше нуля, показывать пользователю сообщение. А если таких нет — запускать базовую логику кнопки OK, которая проведёт сохранение и закрытие карточки.

В системе есть похожие проверки с помощью Select? Если -да, то где я могу их посмотреть?

Правильно понимаю?:

var select = new Select(userConnection)
.Column("%Имя колонки Инвент.номер%")
.From(%раздел КЕ%)
.Where(Column.Const("%Имя колонки Инвент.номер%")).IsEqual(%Введенный Инвент.Номер%);

А IsEqual(%Введенный Инвент.Номер%) - здесь что имеется в виду?

Нет, неправильно. В Const передавать значение, а не название поля.

в Const передавать значение: это значение ч/з Guid получать?

и еще вопрос: не поняла, select – это что будет? Да или НЕТ? Т.е. как я пойму, что в таблице найдены значения колонки?

Татьяна, класс Select — это представление обычных SQL-запросов. Напишите сначала запрос в СУБД, убедитесь, что он работает правильно и возвращает что нужно, и тогда переписывайте на C#.

// выбираю все записи в КЕ, где значение колонки ITNumber равно конкретному значению, выбранному не из справочника.

// На обработчике нажатии ОК в карточке КЕ:

var text = Page.ITNumberEdit.Value;

var select = new Select(userConnection)
.Column(Column.Asterisk())
.From("ConfigurationsItem")
.Where(Column.Const("text")).IsEqual("ITNumber");

// дальше нужно сравнивать, найдено или нет такое же значение?

Не забудьте также, что при редактировании записи (а не созании новой) в базе уже будет запись с таким кодом. То есть в запросе нужно отбросить запись с Id как у записи, открытой в карточке.

И кавычки вокруг text лишние.

Подскажите, пожалуйста, каким методом на С# можно сравнить, найдено или нет такое же значение?

Татьяна, напишите сначала SQL-запрос, который удовлетворяет нужную потребность, затем переведите на C#. Поскольку проверяется только факт наличия или отсутствия, лучше вытягивать не все колонки, а только Id.

Затем делаете чтение из Select и если в нём было хотя бы значение, то одно, если нет — то другое.

using (var dbExecutor = UserConnection.EnsureDBConnection()) {
	using (IDataReader dr = select.ExecuteReader(dbExecutor)) {
		if (dr.Read()) {
			//do something
		} else {
			//do something else
		}
 
	}
}

Посмотрите многочисленные примеры в конфигурации, там Select используется часто.

var text = Page.ITNumberEdit.Value;

SELECT *
FROM ConfigurationsItem
WHERE ITNumber = text;

так?

var text = Page.ITNumberEdit.Value;

SELECT Id
FROM ConfigurationsItem
WHERE ITNumber = text;

так?

Татьяна, ну возьмите базу и проверьте.

"Зверев Александр" написал:

Не забудьте также, что при редактировании записи (а не созании новой) в базе уже будет запись с таким кодом. То есть в запросе нужно отбросить запись с Id как у записи, открытой в карточке.

Добрый день

var select = new Select(UserConnection);
- ошибка "имя UserConnection отсутствует в текущем контексте" исчезла.

осталось две ошибки

Татьяна, почитайте текст сообщения. Оно требует подключения нужного using (пространства имён).
Они подключаются в дереве элементов БП. Какого именно — можно помотреть в аналогичных случаях других карточек, где есть работа с классом Select.

Открыла исх.код на странице редактирования Конф.единицы - там нет using Terrasoft.Core.DB.Query;
Заходила в каждый элемент БП страницы редактирования Конф.Единицы и объекта Конф.единица - не нашла, где идет подключения using. Не там смотрю?

Using в дереве справа в редакторе процессов БП. Откройте любой другой аналогичный процесс и посмотрите, что подключать.

добавила в Usings:
Пространство имен: System.Data.IDataReader
Псевдоним: IDataReader

При опубликовании осталась только одна ошибка:

Если добавить в Using : Terrasoft.Core.DB.Query, то при опубликовании выходит ошибка о том, что Terrasoft.Core.DB.Query является типом, а не пространством имен.

Добавьте лучше Terrasoft.Core.DB

Terrasoft.Core.DB - это я уже добавила ранее

В таком случае рекомендую найти другой процесс, в котором используется Select, и посмотреть, какие подключены там и как всё сделано на уровне кода. Возможно, допущена где-то опечатка.

смотрела на странице редактирования карточки задачи, инцидента, запроса на изменение - все тоже самое, что и здесь. Подскажите, где еще можно уточнить? Может быть, какие -нибудь ссылки на документацию по С# ?

Либо не добавлено нужное Using, либо добавлено ненужное, либо опечатки в коде.
Раз везде работает, а тут нет, значит, не то же самое.
Попробуйте сравнить существующий код с новым, скопировать из существующего.
Документация по работе с Select.

В документации:
Select.ExecuteReader(DBExecutor) - метод
Terrasoft.Core.DB - пространство имен > Select - класс > ExecuteReader - метод : ExecuteReader(DBExecutor) - метод

в Using у меня указано Terrasoft.Core.DB

Тем не менее при опубликовании выходит ошибка:

Не знаю, может у Вас там в названии «ExecuteReader» нелатинские буквы оказались?

все латинское - проверяла.

В таком случае попробуйте написанный вами код в другом месте и код из другого места — в этом.
Нужно понять, дело в коде или в Using.

Нет, ошибка сохраняется:

Причем, если я напишу "Execute" вместо «ExecuteReader», то ошибка уже:


Можно ли каким-нибудь другим способом выполнить проверку на уникальность значения поля?

Можно настроить уникальность на уровне базы.

Написала на обработчике нажатия ОК, после чего откомпилировалось без проблем:

var recordId = new Guid(Page.GetParameterValue("recordId").ToString());
var text = Page.ITNumberEdit.Value;

/*var select = SELECT ("recordId")
.FROM ("ConfigurationsItem")
.WHERE (("ITNumber" = text)&&("Id" != recordId));*/

var select = new Terrasoft.Core.DB.Select(context.UserConnection)
.Column(Column.Asterisk())
.From("ConfigurationsItem")
.Where(Column.Const(text)).IsEqual("ITNumber") as Terrasoft.Core.DB.Select;

using (var DBExecutor = UserConnection.EnsureDBConnection())
{
using (var reader = select.ExecuteReader(DBExecutor))
{
if (reader.Read())
{
//do something
Page.BaseMessagePanel.AddMessage(Warning, "Внутр.инвент.номер (ИТ) должен быть уникальным! ", MessageType.Warning);
return false;
}

else

IsServicesClosing = false;
var configurationItem = Page.DataSource.ActiveRow as Terrasoft.Configuration.ConfigurationItem;
if (configurationItem == null || configurationItem.StatusId == configurationItem.GetTypedOldColumnValue("StatusId")) {
return true;
}

if (!SetWrittenOffOnEditEnabled()) {
var entitySchemaManager = Page.Schema.SchemaManagerProvider.GetManager("EntitySchemaManager") as EntitySchemaManager;
var schema = entitySchemaManager.GetInstanceByName("ServiceInConfigurationItem");
var entitySchemaQuery = new EntitySchemaQuery(entitySchemaManager, schema.Name);
var idColumn = entitySchemaQuery.AddColumn(schema.PrimaryColumn.Name);
entitySchemaQuery.Filters.Add(entitySchemaQuery.CreateFilterWithParameters(
FilterComparisonType.Equal, "ConfigurationItem", configurationItem.Id));
var collection = entitySchemaQuery.GetEntityCollection(UserConnection);
IsServicesClosing = collection.Count > 0;
}
}}
return true;

Но если изменили поле ITNumber в карточке КЕ и хотим сохранить карточку, то система выдает ошибку:

Это значит, что у Вас в конфигурации нет объекта «ConfigurationsItem».

Да, спасибо, все сработало. Но эта логика работает при создании новой карточки КЕ, а если берем уже существующую, то ее ИД нужно убрать из выборки.

var recordId = new Guid(Page.GetParameterValue("recordId").ToString());

Подскажите, пожалуйста, как это учесть в Select ?

Показать все комментарии