Как я могу получить максимальную длину поля DA C без использования fieldname.Length? - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть запрос клиента на сопоставление значения SOOrder.ShipTermsID с «совпадающим» значением SOOrder.ShipVia, когда для записи SO выбран SOOrder.ShipVia (здесь «совпадение» означает, что идентификаторы идентичны настолько, насколько они могут быть). Они хотят, чтобы эти поля всегда соответствовали. Поэтому я начал со следующего в моем расширении SOOrderEntry:

\\other using statements
using PX.Objects.CS;

namespace PX.Objects.SO
{
    public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
    {
        protected virtual void _(Events.FieldUpdated<SOOrder, SOOrder.shipVia> e)
        {
            if (e.Row == null || e.Row.ShipVia == null) return;
            ShipTerms term = PXSelectReadonly<ShipTerms,
                Where<ShipTerms.shipTermsID, Equal<Required<ShipTerms.shipTermsID>>>>
                .Select(Base, e.Row.ShipVia);
            e.Row.ShipTermsID = term?.ShipTermsID;
        }
    }
}

Однако поля SOOrder.ShipVia и SOOrder.ShipTermsID не имеют одинаковую длину. Это nvarchar (15) и nvarchar (10), соответственно, в объявлениях DB и DA C.

ОК, хорошо, поэтому мне нужно обрезать значение из ShipVia до той же длины ShipTermsID. НО, в случае, если это значение когда-либо изменится в Acumatica, я хочу написать свой код, чтобы он не зависел от жестко заданного значения. Итак, моей следующей мыслью было сделать следующее:

    protected virtual void _(Events.FieldUpdated<SOOrder, SOOrder.shipVia> e)
    {
        if (e.Row == null || e.Row.ShipVia == null) return;
        ShipTerms term = PXSelectReadonly<ShipTerms,
            Where<ShipTerms.shipTermsID, Equal<Required<ShipTerms.shipTermsID>>>>
            .Select(Base, e.Row.ShipVia.Substring(0, e.Row.ShipTermsID.Length));
        e.Row.ShipTermsID = term?.ShipTermsID;
    }

Но это не удалось, потому что значение e.Row.ShipTermsID на этом этапе равно NULL, поэтому длина возвращается NULL, а на экране возникает исключение.

Я нашел в Интернете массу информации о том, как получить информацию о схеме БД, но все, что я нашел, похоже, хочет, чтобы я открыл новую строку подключения к БД. Я не уверен, что это лучший подход, и меня беспокоят потенциальные проблемы с производительностью. Кроме того, в случае, если поле DA C будет всегда короче, чем поле DB, информация о схеме в любом случае не будет полезна, поэтому мне нужна длина поля DA C.

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

Как извлечь максимальную длину поля DA C из поля без использования fieldname.Length?

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Начиная с версии Acumatica 2018R2, есть и другой способ сделать то же самое или даже настроить любое свойство атрибута с помощью метода PXCache.Adjust. Этот способ одобрен командой платформы Acumatica, и он лучше, чем PXCache.GetAttributesReadOnly из-за более высокого уровня кода.

protected virtual void _(Events.FieldUpdated<SOOrder, SOOrder.shipVia> e)
{
    if (e.Row == null || e.Row.ShipVia == null) return;

    int length = 0;
    e.Cache.Graph.Caches[typeof(ShipTerms)]
        .Adjust<PXDBStringAttribute>()
        .For<ShipTerms.shipTermsID>(attr => length = attr?.Length ?? 0);

    ShipTerms term = PXSelectReadonly<ShipTerms,
        Where<ShipTerms.shipTermsID, Equal<Required<ShipTerms.shipTermsID>>>>
        .Select(Base, e.Row.ShipVia.Substring(0, Math.Min(e.Row.ShipVia.Length, length)));
    e.Row.ShipTermsID = term?.ShipTermsID;
}
1 голос
/ 27 февраля 2020

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

protected virtual void _(Events.FieldUpdated<SOOrder, SOOrder.shipVia> e)
{
    if (e.Row == null || e.Row.ShipVia == null) return;

    int lenght = e.Cache.Graph.Caches[typeof(ShipTerms)]
        .GetAttributesReadonly<ShipTerms.shipTermsID>()
        .OfType<PXDBStringAttribute>()
        .FirstOrDefault()?.Length ?? 0;

    ShipTerms term = PXSelectReadonly<ShipTerms,
        Where<ShipTerms.shipTermsID, Equal<Required<ShipTerms.shipTermsID>>>>
        .Select(Base, e.Row.ShipVia.Substring(0, Math.Min(e.Row.ShipVia.Length, length)));
    e.Row.ShipTermsID = term?.ShipTermsID;
}
...