Acumatica - 交叉引用
Acumatica - Cross Referencing
我的DAC和表格定义如下
数据结构
ParentTableDAC(窗体视图)
ChildDac1 (TAb1/Grid)
ChildDac2 (Tab2/Grid)
在 ChildDAc2 中,ChildDAc1ID 需要显示为 Selector,如何实现?
如果未为 Parent/ChildDAc1 保存数据,我们将面临问题,那么它对 ChildDAc2 Lookup
不可用
更新-
业务场景 -
一个工作项有多个任务和多个步骤来执行该工作项。
现在 WORKITEMDAC 是父项
TASKDAC 和 STEPDAC 是父 WORKITEMDAC 的子对象。
好的,直到一切都正常。
现在假设每个步骤都与父 WORKITEM 的任务相关联。
因此在 STEPS Grid 中需要一个选择器来 select 任务。
在这里我有适当的父子关系没有问题,我只有一个问题,我可以 select 只有已经用父 WORKITEM 保存的任务,未保存的任务不会显示在 select或者。
所以我的问题是,我们有没有办法在尚未保存的 PXSelector 查询中获取任务?
以下选择器用于 TaskID 列上的 STEPDAC -
[PXSelector(typeof(Search>>), typeof(TASKDAC.taskCD), SubstituteKey = typeof(TASKDAC.taskCD))]
注意 - TASKDAC 中的 TaskID 列是标识列,此 DAC 将 WorkItemID 定义为 PArent。
更新
感谢您提供更详细的更新。为那些可能需要有关 parent/child.
的人保留下面的原始回复
我从未见过 select 或参考 Current<> 而没有 Current WHAT 的定义。老实说,我很惊讶它的编译。 “Where Field = Current View Field”指示 selector 将结果限制为仅与您指定的任何字段的当前值关联的值,并且它是从图表中的“ViewName.Current”记录中检索的.您的 where 子句没有告诉它匹配什么“当前”。由于您将 selector 指向搜索,我怀疑这会导致 selector 无法找到匹配的记录并且 short-circuiting 无法保存该字段的结果。
听起来 TASKDAC 是一种“主数据”类型的记录,定义了所有可能要执行的任务。因此,TaskID 不是 STEPDAC 中的关键字段,而是 TASKDAC 中的关键字段。如果你想 select “任何”任务,你根本不需要 where 子句。
[PXSelector(
typeof(TASKDAC.TaskID),
typeof(TASKDAC.taskCD),
SubstituteKey = typeof(TASKDAC.taskCD)
)]
让我们暂时假设您指定一个 WORKITEMDAC.WorkOrderType 用于按同一字段过滤 acceptable 任务。 (只能将维修任务分配给维修 WorkOrderType,将装配分配给装配 WorkOrderType,等等)在这种情况下,您将使用您声明的语法,但您将指定 Where>。如果任务仅限于 STEPDAC 中的某些内容,只需在下面的示例中将 WORKITEMDAC 替换为 STEPDAC 字段即可。
[PXSelector(
typeof(Search<TASKDAC.TaskID,
Where<TASKDAC.WorkOrderType, Equal<Current<WORKITEMDAC.WorkOrderType>>>>),
typeof(TASKDAC.taskCD),
SubstituteKey = typeof(TASKDAC.taskCD)
)]
请更新您的 PXSelector 并告知是否可以解决问题或接下来会出现什么错误。
原始回复
你的问题太少了,你的问题的性质很不清楚。听起来您正在尝试做一些可能应该采取不同方法的事情。 selector 的定义不应影响字段的保存,但 parent child 关系的结构对于正确定义至关重要。因此,您拥有一个不同于 parent 的 Child ID 并且它会在 selector.
中使用,这似乎很奇怪
通常,child DAC 与 parent DAC 共享一个 ID。我们经常在child中定义一个LineNbr字段,由PXLineNbrAttribute赋值,Key字段为ID+LineNbr来标识特定的child记录。我们还在网格上的 ASPX 文档中设置 SyncPosition = true,以便用户界面与用户在网格中 selected 的任何记录保持完全同步。 Parent Child 关系可以菊花链式连接,例如 SOOrder -> SOLine -> SOLineSplit,但最终,child 的 ID 字段不是 selector。 .. parent 的 ID 是
将 selector 视为查找主数据的一种方式。主数据可能与其他数据相关,但在大多数情况下不会有 parent。有例外,但让我们保持简单。例如,采购订单不会有 parent,关键字段将是一个常见的 selector 字段。但是,由于 child 必须始终与其 parent 相关并且不能更改其 parent,因此 child 字段的 ID 不会是 selector。 Acumatica 中的其他 table 会引用某些字段或字段组合以与 child DAC 的数据相关。
为了说明这一点,我从 T210 培训指南中删除了很多内容。
RSSVRepairPrice - Parent
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 - Child
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
}
}
在parent中,注意PXDBIdentityAttribute 的使用,它指定记录标识由数据库在PriceID 中设置。 child 使用的“ID”字段取自定义为 select 或另一个主 table 的 ServiceID 字段。在 PXDBIntAttribute 上使用 IsKey = true 告诉 Acumatica 它可以通过标记为 IsKey = true 的所有字段的组合找到唯一记录。 (请注意,实际培训指南包括另一个字段作为键的一部分,但我在这里简化了示例。)还要注意使用默认值为 0 的 PDXBInt 字段用作行计数器。 (RepairItemLineCtr)
现在,在 child 中,请注意 parent 的关键字段在 DAC 中再次定义,但没有 selector。 PXParent 属性定义了与 parent DAC 的关系,字段值默认来自 parent。这就是导致值自动保存在记录中的原因。它还关联关系,以便删除 parent 也会删除 child。请注意使用 PXLineNbrAttribute 来自动递增 parent DAC 的字段并在 LineNbr 字段中设置值。正是这 2 个字段的组合将您指向确切的记录。
在某些情况下,Acumatica 使用 NoteID 字段(一个独特的 GUIvalue) 来识别 child DAC 的记录,但这有点复杂。您可以在 INItemPlan(需求)与采购订单的关系中看到它。
如果您在 Parent-Child (Master-Detail) 关系方面遇到问题,我强烈建议您查看 T210 training course。
要引用未保存的数据,请在 PXSelector 上使用 ISDirty =true。
还要在引用位置保存未保存数据的标识键值,使用 [PXDBDefault()]
我的DAC和表格定义如下 数据结构
ParentTableDAC(窗体视图) ChildDac1 (TAb1/Grid) ChildDac2 (Tab2/Grid)
在 ChildDAc2 中,ChildDAc1ID 需要显示为 Selector,如何实现? 如果未为 Parent/ChildDAc1 保存数据,我们将面临问题,那么它对 ChildDAc2 Lookup
不可用更新-
业务场景 -
一个工作项有多个任务和多个步骤来执行该工作项。
现在 WORKITEMDAC 是父项
TASKDAC 和 STEPDAC 是父 WORKITEMDAC 的子对象。
好的,直到一切都正常。
现在假设每个步骤都与父 WORKITEM 的任务相关联。
因此在 STEPS Grid 中需要一个选择器来 select 任务。
在这里我有适当的父子关系没有问题,我只有一个问题,我可以 select 只有已经用父 WORKITEM 保存的任务,未保存的任务不会显示在 select或者。
所以我的问题是,我们有没有办法在尚未保存的 PXSelector 查询中获取任务?
以下选择器用于 TaskID 列上的 STEPDAC -
[PXSelector(typeof(Search
注意 - TASKDAC 中的 TaskID 列是标识列,此 DAC 将 WorkItemID 定义为 PArent。
更新
感谢您提供更详细的更新。为那些可能需要有关 parent/child.
的人保留下面的原始回复我从未见过 select 或参考 Current<> 而没有 Current WHAT 的定义。老实说,我很惊讶它的编译。 “Where Field = Current View Field”指示 selector 将结果限制为仅与您指定的任何字段的当前值关联的值,并且它是从图表中的“ViewName.Current”记录中检索的.您的 where 子句没有告诉它匹配什么“当前”。由于您将 selector 指向搜索,我怀疑这会导致 selector 无法找到匹配的记录并且 short-circuiting 无法保存该字段的结果。
听起来 TASKDAC 是一种“主数据”类型的记录,定义了所有可能要执行的任务。因此,TaskID 不是 STEPDAC 中的关键字段,而是 TASKDAC 中的关键字段。如果你想 select “任何”任务,你根本不需要 where 子句。
[PXSelector(
typeof(TASKDAC.TaskID),
typeof(TASKDAC.taskCD),
SubstituteKey = typeof(TASKDAC.taskCD)
)]
让我们暂时假设您指定一个 WORKITEMDAC.WorkOrderType 用于按同一字段过滤 acceptable 任务。 (只能将维修任务分配给维修 WorkOrderType,将装配分配给装配 WorkOrderType,等等)在这种情况下,您将使用您声明的语法,但您将指定 Where
[PXSelector(
typeof(Search<TASKDAC.TaskID,
Where<TASKDAC.WorkOrderType, Equal<Current<WORKITEMDAC.WorkOrderType>>>>),
typeof(TASKDAC.taskCD),
SubstituteKey = typeof(TASKDAC.taskCD)
)]
请更新您的 PXSelector 并告知是否可以解决问题或接下来会出现什么错误。
原始回复
你的问题太少了,你的问题的性质很不清楚。听起来您正在尝试做一些可能应该采取不同方法的事情。 selector 的定义不应影响字段的保存,但 parent child 关系的结构对于正确定义至关重要。因此,您拥有一个不同于 parent 的 Child ID 并且它会在 selector.
中使用,这似乎很奇怪通常,child DAC 与 parent DAC 共享一个 ID。我们经常在child中定义一个LineNbr字段,由PXLineNbrAttribute赋值,Key字段为ID+LineNbr来标识特定的child记录。我们还在网格上的 ASPX 文档中设置 SyncPosition = true,以便用户界面与用户在网格中 selected 的任何记录保持完全同步。 Parent Child 关系可以菊花链式连接,例如 SOOrder -> SOLine -> SOLineSplit,但最终,child 的 ID 字段不是 selector。 .. parent 的 ID 是
将 selector 视为查找主数据的一种方式。主数据可能与其他数据相关,但在大多数情况下不会有 parent。有例外,但让我们保持简单。例如,采购订单不会有 parent,关键字段将是一个常见的 selector 字段。但是,由于 child 必须始终与其 parent 相关并且不能更改其 parent,因此 child 字段的 ID 不会是 selector。 Acumatica 中的其他 table 会引用某些字段或字段组合以与 child DAC 的数据相关。
为了说明这一点,我从 T210 培训指南中删除了很多内容。
RSSVRepairPrice - Parent
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 - Child
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
}
}
在parent中,注意PXDBIdentityAttribute 的使用,它指定记录标识由数据库在PriceID 中设置。 child 使用的“ID”字段取自定义为 select 或另一个主 table 的 ServiceID 字段。在 PXDBIntAttribute 上使用 IsKey = true 告诉 Acumatica 它可以通过标记为 IsKey = true 的所有字段的组合找到唯一记录。 (请注意,实际培训指南包括另一个字段作为键的一部分,但我在这里简化了示例。)还要注意使用默认值为 0 的 PDXBInt 字段用作行计数器。 (RepairItemLineCtr)
现在,在 child 中,请注意 parent 的关键字段在 DAC 中再次定义,但没有 selector。 PXParent 属性定义了与 parent DAC 的关系,字段值默认来自 parent。这就是导致值自动保存在记录中的原因。它还关联关系,以便删除 parent 也会删除 child。请注意使用 PXLineNbrAttribute 来自动递增 parent DAC 的字段并在 LineNbr 字段中设置值。正是这 2 个字段的组合将您指向确切的记录。
在某些情况下,Acumatica 使用 NoteID 字段(一个独特的 GUIvalue) 来识别 child DAC 的记录,但这有点复杂。您可以在 INItemPlan(需求)与采购订单的关系中看到它。
如果您在 Parent-Child (Master-Detail) 关系方面遇到问题,我强烈建议您查看 T210 training course。
要引用未保存的数据,请在 PXSelector 上使用 ISDirty =true。 还要在引用位置保存未保存数据的标识键值,使用 [PXDBDefault()]