身份字段作为自定义表的关键

时间:2018-01-17 21:34:46

标签: acumatica

我有两个自定义表(标题/详细信息),它们有多个字段作为两者的键。我已经在Header的详细选择中创建了所有PXParent和PXDefault属性,就像在T200课程中所示。

问题在于,当我在标题部分有关键字段并尝试创建新记录时,表单不会清除我为这些关键字段选择的值。

我继续创建一个自动递增的int标识字段作为键,而其他以前的关键字段组装成一个唯一的索引。我在我的DAC中使用PXDBIdentity(IsKey = true)属性 - 除了一个问题之外它运行良好:当我创建一个新记录时,该字段显示-2147483647直到我保存,然后它显示新创建的标识值

所以我想我的问题是:

当该表的唯一标识由6个字段组成时,为自定义表创建关键字段的标准协议/最佳实践是什么?如果我正确地做了,如何消除-2147483647在ID字段中的显示?

2 个答案:

答案 0 :(得分:0)

标识字段的问题在于数字是由数据库生成的,而不是由ORM生成的,ORM通常在记录持续存储之前保存缓存中的新插入行。我的建议是从UI中删除身份或找出不同的密钥。

答案 1 :(得分:0)

在定义DAC中的关键字段时,只有一条主要规则:

  • 只有绑定到标识列的字段才能成为DAC中唯一的关键字段

  • 只要没有定义的关键字段绑定到标识列,您就可以在DAC中定义几个关键字段

框架提供的标准 PXInsert 操作会保留除最后一个之外的所有关键字段的值。如果希望“插入”按钮清除所有键字段的值,则可以从PXInsert<TNode>类继承并在执行基本逻辑之前清除搜索数组:

public class MyGraph : PXGraph<MyGraph>
{
    public class PXInsertCst<TNode> : PXInsert<TNode>
        where TNode : class, IBqlTable, new()
    {
        public PXInsertCst(PXGraph graph, string name)
        : base(graph, name)
        {
        }
        public PXInsertCst(PXGraph graph, Delegate handler)
            : base(graph, handler)
        {
        }

        [PXUIField(DisplayName = ActionsMessages.Insert, 
             MapEnableRights = PXCacheRights.Insert, 
             MapViewRights = PXCacheRights.Insert)]
        [PXInsertButton]
        protected override IEnumerable Handler(PXAdapter adapter)
        {
            adapter.Searches = null;
            return base.Handler(adapter);
        }
    }

    public PXSave<MyPrimaryDAC> Save;
    public PXCancel<MyPrimaryDAC> Cancel;

    // The standard PXInsert type was replaced with the custom PXInsertCst type
    public PXInsertCst<MyPrimaryDAC> Insert;

    public PXDelete<MyPrimaryDAC> Delete;
    public PXCopyPasteAction<MyPrimaryDAC> CopyPaste;
    public PXFirst<MyPrimaryDAC> First;
    public PXPrevious<MyPrimaryDAC> Previous;
    public PXNext<MyPrimaryDAC> Next;
    public PXLast<MyPrimaryDAC> Last;
}

如果要求显示唯一的DAC键字段绑定UI中的标识列,但用户不希望看到为新记录生成的临时负值,则应实现<以下代码示例后面的DAC的标识列映射字段的strong> FieldSelecting 和 FieldUpdating 事件处理程序:

public class MyGraph : PXGraph<MyGraph>
{
    protected void MyDAC_IdentityField_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
    {
        if (e.Row != null && e.ReturnValue is int?)
        {
            if ((e.ReturnValue as int?).GetValueOrDefault() < 0)
            {
                e.ReturnValue = null;
            }
        }
    }

    protected void MyDAC_IdentityField_FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
    {
        if (e.Row != null && e.NewValue == null && sender.Inserted.Count() == 1)
        {
            var defaultValue = sender.GetValue<MyDAC.identityField>(sender.Inserted.FirstOrDefault_());
            if (defaultValue != null)
            {
                e.NewValue = defaultValue;
            }
        }
    }
}

对于DAC级别的更通用方法,您可以实现从PXDBIdentityAttribute继承的自定义属性,并在代码后面覆盖 FieldSelecting FieldUpdating 事件处理程序示例如下:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | 
     AttributeTargets.Class | AttributeTargets.Method)]
public class PXDBNewIdentityAttribute : PXDBIdentityAttribute
{
    public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
    {
        base.FieldSelecting(sender, e);

        if (e.Row != null && e.ReturnValue is int?)
        {
            if ((e.ReturnValue as int?).GetValueOrDefault() < 0)
            {
                e.ReturnValue = null;
            }
        }
    }

    public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
    {
        if (e.Row != null && e.NewValue == null && sender.Inserted.Count() == 1)
        {
            var defaultValue = sender.GetValue(sender.Inserted.FirstOrDefault_(), FieldOrdinal);
            if (defaultValue != null)
            {
                e.NewValue = defaultValue;
            }
        }

        base.FieldUpdating(sender, e);
    }
}