首页 > 解决方案 > Acumatica - 交叉参考

问题描述

我的 DAC 和表定义如下 数据结构

ParentTableDAC (FormView) ChildDac1 (TAb1/网格) ChildDac2 (Tab2/网格)

在 ChildDAc2 中,ChildDAc1ID 需要显示为选择器,如何做到这一点?如果没有为 Parent/ChildDAc1 保存数据,我们将面临问题,那么它对 ChildDAc2 查找不可用

更新 - 业务场景 - 一个工作项具有多个任务和多个步骤来执行该工作项。现在 WORKITEMDAC 是父 TASKDAC,STEPDAC 是父 WORKITEMDAC 的子。好的,直到一切正常并且正常..现在每个步骤都应该与父 WORKITEM 的任务相关联。所以在 STEPS Grid 中需要一个选择器来选择任务。在这里我有正确的父子关系没有问题,我只有一个问题,我只能选择已经与父WORKITEM一起保存的任务,未保存的任务不会显示在选择器中。所以我的问题是,我们有没有办法在 PXSelector 查询中获取尚未保存的任务?以下 Selector 用于 STEPDAC 上 TaskID 列 - [PXSelector(typeof(Search<TASKDAC.TaskID, Where<TASKDAC.taskID, Equal<Current>>>), typeof(TASKDAC.taskCD), SubstituteKey = typeof(TASKDAC.taskCD))]

注意 - TASKDAC 中的 TaskID 列是标识列,并且此 DAC 将 WorkItemID 定义为 PArent。

标签: foreign-keysacumatica

解决方案


更新

感谢您更新更多细节。将原始回复留在下面,以供可能需要有关父母/孩子的人使用。

我从未见过参考 Current<> 定义的选择器,也没有看到 Current WHAT。老实说,我很惊讶它编译。“Where Field = Current View Field”指示选择器将结果限制为仅与您指定的任何字段的当前值相关联的值,并从图中的“ViewName.Current”记录中检索。您的 where 子句没有告诉它匹配什么“当前”。由于您将选择器定向到搜索,我怀疑这会导致选择器无法找到匹配的记录并导致该字段结果的保存短路。

听起来 TASKDAC 是一个“主数据”类型的记录,定义了所有可能要执行的任务。因此,TaskID 不是 STEPDAC 中的关键字段,而是 TASKDAC 中的关键字段。如果要选择“任何”任务,则根本不需要 where 子句。

[PXSelector(
    typeof(TASKDAC.TaskID),
    typeof(TASKDAC.taskCD),
    SubstituteKey = typeof(TASKDAC.taskCD)
)]

让我们暂时假设您指定一个 WORKITEMDAC.WorkOrderType 用于按相同字段过滤可接受的任务。(只能将修复任务分配给修复 WorkOrderType,将装配分配给装配 WorkOrderType 等。)在这种情况下,您将使用您声明的语法,但您将指定 Where<TASKDAC.WorkOrderType, Equal<Current<WORKITEMDAC.WorkOrderType >>。如果任务仅限于 STEPDAC 中的某些内容,只需将 WORKITEMDAC 替换为下面示例中的 STEPDAC 字段即可。

[PXSelector(
    typeof(Search<TASKDAC.TaskID,
        Where<TASKDAC.WorkOrderType, Equal<Current<WORKITEMDAC.WorkOrderType>>>>),
    typeof(TASKDAC.taskCD),
    SubstituteKey = typeof(TASKDAC.taskCD)
)]

请更新您的 PXSelector 并告知是否可以解决问题或您接下来会遇到什么错误。

原始回复

您的问题很少,您的问题的性质非常不清楚。听起来您正在尝试做一些可能应该采取不同方法的事情。选择器的定义不应影响字段的保存,但正确定义父子关系的结构至关重要。因此,您的子 ID 与父 ID 不同,并且会在选择器中使用,这似乎很奇怪。

通常,子 DAC 与父 DAC 共享一个 ID。我们经常在孩子中定义一个 LineNbr 字段,它由 PXLineNbrAttribute 赋予一个值,并且 Key 字段将是 ID + LineNbr 以标识特定的子记录。我们还在网格上的 ASPX 文档中设置 SyncPosition = true,以便用户界面与用户在网格中选择的任何记录保持完全同步。父子关系可以菊花链式连接,例如使用 SOOrder -> SOLine -> SOLineSplit,但最终,子项的 ID 字段不是选择器……父项的 ID 是。

将选择器视为查找主数据的一种方式。主数据可能与其他数据相关,但在大多数情况下它没有父数据。有例外,但让我们保持简单。例如,采购订单没有父级,关键字段将是一个公共选择器字段。但是,由于子项必须始终与其父项相关并且不能更改其父项,因此子字段的 ID 不会是选择器。Acumatica 中的其他表将引用某个字段或字段组合以与子 DAC 的数据相关。

从 T210 培训指南中,我剥离了很多内容来说明这一点。

RSSVRepairPrice - 父级

using System;
using PX.Data;

namespace PhoneRepairShop
{
    [PXCacheName("Repair Price")]
    public class RSSVRepairPrice : IBqlTable
    {
        #region PriceID
        [PXDBIdentity]
        public virtual int? PriceID { get; set; }
        public abstract class priceID : PX.Data.BQL.BqlInt.Field<priceID> { }
        #endregion

        #region ServiceID
        [PXDBInt(IsKey = true)]
        [PXDefault]
        [PXUIField(DisplayName = "Service", Required = true)]
        [PXSelector(
            typeof(Search<RSSVRepairService.serviceID>),
            typeof(RSSVRepairService.serviceCD),
            typeof(RSSVRepairService.description),
            DescriptionField = typeof(RSSVRepairService.description),
            SelectorMode = PXSelectorMode.DisplayModeText)]
        public virtual int? ServiceID { get; set; }
        public abstract class serviceID : PX.Data.BQL.BqlInt.Field<serviceID> { }
        #endregion

        #region RepairItemLineCntr
        [PXDBInt()]
        [PXDefault(0)]
        public virtual Int32? RepairItemLineCntr { get; set; }
        public abstract class repairItemLineCntr : PX.Data.BQL.BqlInt.Field<repairItemLineCntr> { }
        #endregion

    }
}

RSSVRepairItem - 孩子

using System;
using PX.Data;
using PX.Objects.IN;
using PX.Data.BQL.Fluent;

namespace PhoneRepairShop
{
    [PXCacheName("Repair Item")]
    public class RSSVRepairItem : IBqlTable
    {
        #region ServiceID
        [PXDBInt(IsKey = true)]
        [PXDBDefault(typeof(RSSVRepairPrice.serviceID))]
        [PXParent(
            typeof(SelectFrom<RSSVRepairPrice>.
            Where<RSSVRepairPrice.serviceID.IsEqual<
            RSSVRepairItem.serviceID.FromCurrent>>
            ))]
        public virtual int? ServiceID { get; set; }
        public abstract class serviceID : PX.Data.BQL.BqlInt.Field<serviceID> { }
        #endregion

        #region LineNbr
        [PXDBInt(IsKey = true)]
        [PXLineNbr(typeof(RSSVRepairPrice.repairItemLineCntr))]
        [PXUIField(DisplayName = "Line Nbr.", Visible = false)]
        public virtual int? LineNbr { get; set; }
        public abstract class lineNbr : PX.Data.BQL.BqlInt.Field<lineNbr> { }
        #endregion

    }
}

在父级中,请注意 PXDBIdentityAttribute 的使用,它指定记录身份由数据库在 PriceID 中设置。子表使用的“ID”字段取自 ServiceID 字段,该字段被定义为另一个主表的选择器。在 PXDBIntAttribute 上使用IsKey = true告诉 Acumatica 它可以通过所有标记为IsKey = true的字段的组合找到唯一记录。(请注意,实际的培训指南包括另一个字段作为键的一部分,但我在这里简化了示例。)还请注意使用默认值为 0 的 PDXBInt 字段用作行计数器。(RepairItemLineCtr)

现在,在子项中,请注意父项的键字段在 DAC 中再次定义,但没有选择器。PXParentAttribute 定义了与父 DAC 的关系,并且该字段值默认来自该父 DAC。这就是导致值自动保存在记录中的原因。它还关联关系,以便删除父级也会删除子级。注意使用 PXLineNbrAttribute 来自动增加父 DAC 的字段并在 LineNbr 字段中设置值。正是这两个字段的组合为您指明了准确的记录。

在某些情况下,Acumatica 使用 NoteID 字段(唯一的 GUID 值)来识别子 DAC 的记录,但这有点复杂。您可以在 INItemPlan(需求)与采购订单的关系中看到它。

如果您在父子(主从)关系方面遇到问题,我强烈建议您查看T210 培训课程


推荐阅读