Acumatica-交叉引用

问题描述

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

ParentTableDAC(FormView) ChildDac1(TAb1 / Grid) ChildDac2(Tab2 / Grid)

在ChildDAc2中,ChildDAc1ID需要显示为选择器,这如何完成? 我们面临的问题是,如果没有为Parent / ChildDAc1保存数据,那么ChildDAc2查找将无法使用

更新- 业务场景- 一个工作项具有多个任务和执行该工作项的多个步骤。 现在WORKITEmdac是父母 TASKDAC和STEPDAC是父级WORKITEmdac的子级。 好的,直到一切正常为止。 现在,假设每个步骤都与“父WORKITEM”的任务相关联。 因此,在“步骤网格”中需要一个选择器来选择任务。 在这里,我具有适当的父子关系,没有任何问题。我只有一个问题,就是我只能选择已经用“父工作项”保存的任务,未保存的任务不会显示在选择器中。 所以我的问题是,我们是否有办法在尚未保存的PXSelector查询获取任务? 在TaskID列的STEPDAC上使用了跟随选择器- [PXSelector(typeof(Search >>),typeof(TASKDAC.taskCD),SubstituteKey = typeof(TASKDAC.taskCD))]

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

解决方法

更新

感谢您进行更详细的更新。对于可能需要有关父母/子女的人,将原始答复留在下面。

我从未见过参考Current 定义的选择器,而没有Current WHAT。老实说,我很惊讶它被编译了。 “位置字段=当前视图字段”指示选择器将结果限制为仅与指定的任何字段的“当前值”关联的值,并从图形的“ ViewName.Current”记录中检索该值。您的where子句不会告诉它要匹配的“当前”值。由于您将选择器定向到搜索,因此我怀疑这导致选择器无法找到匹配的记录,并使该字段的结果保存短路。

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

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

让我们暂时假设您指定了一个WORKITEMDAC.WorkOrderType,它用于按同一字段过滤可接受的任务。 (只能将维修任务分配给维修WorkOrderType,将装配分配给装配WorkOrderType,等等。)在这种情况下,您将使用所声明的语法,但是将指定Where >。如果任务只限于在STEPDAC中执行,则在下面的示例中将WORKITEMDAC替换为STEPDAC字段。

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

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

原始回复

问题不多,问题的性质尚不清楚。听起来您正在尝试做一些可能应该采用不同方法的事情。选择器的定义不应影响字段的保存,但是父子关系的结构对于正确定义至关重要。因此,您有一个不同于父代的子代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 training course

,

要引用未保存的数据,请在PXSelector上使用ISDirty = true。 还可以将未保存数据的标识密钥值保存在引用位置,请使用[PXDBDefault()]