#unique #acumatica
#уникальная #acumatica
Вопрос:
Какой атрибут можно использовать, чтобы разрешить уникальные значения, мы использовали [PXUniqueCheck(typeof(Name))] Но если используется представление списка и записи обновляются с тем же именем, оно допускает одинаковые значения имени
Более подробно — ПРИВЕТ, столбец отмечен IsKey = True для имени, мое представление — ListView, с двумя полями Name и Description, где Name имеет IsKey = True, а другой идентификатор столбца имеет атрибут DBIdentity. ИТАК, я думаю, что с DAC все в порядке, пользовательский интерфейс добавляет поведение — когда добавляется существующее значение, оно обновляет старую строку новым добавленным описанием значения, поскольку имя такое же. Поведение обновления — Измените столбец name на то же значение, что и у other, тогда это позволит иметь 2 строки с одинаковым ключом, но обе строки отображают одно и то же описание в пользовательском интерфейсе, но в DB есть 2 строки с одинаковым значением Name и разным описанием
DAC —
[System.SerializableAttribute()]
[PXPrimaryGraph(typeof(TestCategoryMaint))]
public class TestCategory : PX.Data.IBqlTable
{
#region TestCategoryID
public abstract class testCategoryID : PX.Data.BQL.BqlInt.Field<testCategoryID>
{
}
protected int? _TestCategoryID;
[PXDBIdentity()]
[LicenseExpiration]
[PXReferentialIntegrityCheck]
public virtual int? TestCategoryID
{
get
{
return this._TestCategoryID;
}
set
{
this._TestCategoryID = value;
}
}
#endregion
#region Name
public abstract class name : PX.Data.IBqlField
{
}
protected string _Name;
[PXDBString(50, IsKey = true, IsUnicode = true, InputMask = "")]
[PXDefault()]
[PXUIField(DisplayName = "Test Category")]
[PXCheckUnique(typeof(name))]
public virtual string Name
{
get
{
return this._Name;
}
set
{
this._Name = value;
}
}
#endregion
#region Description
public abstract class description : PX.Data.IBqlField
{
}
protected string _Description;
[PXDBString(255,IsUnicode =true)]
[PXUIField(DisplayName = "Description")]
public virtual string Description
{
get
{
return this._Description;
}
set
{
this._Description = value;
}
}
#endregion
Комментарии:
1. Если вам нужны уникальные значения, рассматривали ли вы возможность добавления IsKey в ваше поле DAC? Похоже, что ваше поле является каким-то типом первичного ключа
2. Iskey добавляется в столбец Identity, который также используется в справочных таблицах, в то время как Name является полем CD
3. Вы можете использовать IsKey в поле CD и по-прежнему использовать столбец identity (без ключа) в качестве ссылки в других таблицах. Ключи таблицы SQL могут отличаться от ключа DAC, что нормально.
4. Дмитрий, да, имя присваивается с помощью IsKey true, но все же в режиме просмотра списка мы можем воспроизвести наличие 2 строк с одинаковыми именами, обновив существующую строку с тем же именем, что и уже имеющуюся в другой строке, а затем она отобразит обе строки с одинаковым значением в пользовательском интерфейсе.
Ответ №1:
Без каких-либо примеров кода того, что вы пытаетесь сделать, трудно гарантировать, что ответ соответствует вашему вопросу, но я постараюсь ответить в широком масштабе.
Основываясь на приведенных выше комментариях, поле идентификации является таковым именно потому, что оно определено как идентификатор в базе данных. Соответствующее поле в DAC должно быть помечено как PXDBIdentity. В Acumatica это обычно определяется как поле идентификатора «ID». Отображаемое вами поле, которое должно оставаться уникальным, как правило, является полем code «CD».
Приведенный ниже пример показывает, как настроить пару, в комплекте с часто используемыми атрибутами. В этом примере поле CD пронумеровано автоматически, но это не обязательно. PXSelector в самом поле помогает сохранить это как уникальное значение, поскольку это позволит вам выбирать из существующего значения, вводить новое значение или извлекать значение, которое было введено с помощью ключа. Фактическая уникальность контролируется комбинацией всех полей, отмеченных IsKey = true.
// This is the Identity field in the database (Use PXDBIdentity)
#region RequisitionID
[PXDBIdentity]
public virtual int? RequisitionID { get; set; }
public abstract class requisitionID
: PX.Data.BQL.BqlInt.Field<requisitionID> { }
#endregion
// This is the user friendly Code (CD) to be unique (IsKey = true)
#region RequisitionCD
[PXDBString(30, IsKey = true, IsUnicode = true, InputMask = "")]
[PXDefault]
[AutoNumber(typeof(SSRQSetup.requisitionNumberingID),
typeof(AccessInfo.businessDate))]
[PXSelector(
typeof(SSRQRequisition.requisitionCD),
typeof(SSRQRequisition.requisitionCD),
typeof(SSRQRequisition.descr)
)]
[PXUIField(DisplayName = Messages.FldRequisitionCD)]
public virtual string RequisitionCD { get; set; }
public abstract class requisitionCD
: PX.Data.BQL.BqlString.Field<requisitionCD> { }
Аналогичным образом, вы можете вернуться к этой комбинации, чтобы при взаимодействии с пользователем использовалось уникальное поле CD, но значение ID сохранялось в записи. Лучше всего использовать поле ID, которое будет общим для всех таблиц, где используется для нормализации базы данных и позволяет изменять отображаемое значение (CD) без необходимости потенциально обновлять десятки других таблиц. Это означает, что любой уникальный объект (товар, поставщик, клиент и т.д.) будет сохраняться в его собственной записи, где значение IsKey однозначно идентифицирует точный объект. Если вам нужно, чтобы ваша конкретная таблица сохраняла это значение в качестве уникальности, то это было бы единственное поле с пометкой IsKey = true, а затем поле identity использовалось бы в других таблицах, ссылающихся на эти данные.
Чтобы использовать эти ключевые данные в других таблицах, вам следует сохранить значение поля ID, но использовать PXSelector для представления значения CD пользователю. Это позволяет хранить очень эффективное числовое значение в базе данных в связанных таблицах, а не значение, которое может состоять из нескольких символов или тысяч символов (в крайнем случае).
#region RequisitionID
[PXDBInt]
[PXSelector(
typeof(SSRQRequisition.requisitionID),
typeof(SSRQRequisition.requisitionCD),
typeof(SSRQRequisition.descr),
SubstituteKey = typeof(SSRQRequisition.requisitionCD)
)]
[PXUIField(DisplayName = Messages.FldRequisitionID)]
public virtual int? RequisitionID { get; set; }
public abstract class requisitionID
: PX.Data.BQL.BqlInt.Field<requisitionID> { }
#endregion
Очень важно понимать, что использование IsKey обеспечит уникальность на основе каждого поля, в котором вы его указали. IsKey обеспечит уникальность только для комбинации всех полей, отмеченных IsKey = true. Похоже, что PXSelector гарантирует, что само поле сохраняется уникальным, а также поле, указанное с помощью SubstituteKey, при использовании в качестве селектора будет извлекать запись, содержащую введенное вами значение. Я использовал это только в случаях ID против CD, но вы могли бы поэкспериментировать с PXSelector и IsKey, если у вас есть какой-либо вариант использования, выходящий за рамки этого ответа.
Комментарии:
1. ПРИВЕТ, столбец отмечен IsKey = True для имени, мое представление — ListView, с двумя полями Name и Description, где Name имеет IsKey = True, а другой идентификатор столбца имеет атрибут DBIdentity. ИТАК, я думаю, что с DAC все в порядке, пользовательский интерфейс добавляет поведение — когда добавляется существующее значение, оно обновляет старую строку новым добавленным описанием значения, поскольку имя такое же. Поведение обновления — Измените столбец name на то же значение, что и у другого, тогда это позволит иметь 2 строки с одинаковым ключом, но обе строки отображают одинаковое описание в пользовательском интерфейсе, но в базе данных есть 2 строки с одинаковым значением имени и разным описанием.
2. Пожалуйста, обновите свой вопрос, чтобы предоставить код для вашего DAC. Любое поле, которое не помечено как IsKey = true или помечено как identity или с использованием PXParent, должно быть в порядке исключения.
Ответ №2:
Приведенный ниже код поможет вам добавлять только уникальные значения, и когда вы пытаетесь добавить повторяющиеся значения, это выдает ошибку.
[PXCheckUniqueCustomError("Order already exists with Customer Order Nbr {0} and External Ref.Nbr {1}", typeof(SOOrder.customerOrderNbr), typeof(SOOrder.customerRefNbr),
Where = typeof(Where2<Where<SOOrder.orderType, Equal<Current<SOOrder.orderType>>,
And<SOOrder.customerOrderNbr, Equal<Current<SOOrder.customerOrderNbr>>,
And<SOOrder.customerRefNbr, Equal<Current<SOOrder.customerRefNbr>>>>>,
And<SOOrder.status, NotEqual<SOOrderStatus.cancelled>>>))]