Acumatica - 已添加具有相同密钥的项目

Acumatica - An item with the same key has already been added

我在 Acumatica 2021R1 (v21.104.0018) 中有自定义项目。我有一个具有 ID 的父 DAC 和多个使用此 ID 和 PXParent 属性的子 DAC。每当我 select 在自定义项目编辑器中设计屏幕时,我都会收到一条错误消息,指出“已添加具有相同键的项目。”然后,我无法在屏幕编辑器中设计屏幕。奇怪的是,当我打开实际屏幕时,我没有收到此消息。

我不确定这是指什么,因为在我用于屏幕图表视图的表格中的数据库中没有任何记录。

不确定其他人是否遇到过这个问题并知道是什么原因造成的,但 Acumatica 确实可以使用一些更具体的错误消息。

这是我的父级 DAC(注意:出于 space 的目的,我在此处省略了系统字段):

    public class PSImport : IBqlTable
    {
        #region Import ID
        [PXDBString(15, IsKey = true, IsUnicode = true, InputMask = ">CCCCCCCCCCCCCCC")]
        [PXDefault(PersistingCheck = PXPersistingCheck.NullOrBlank)]
        [PXUIField(DisplayName = "Import No.", Visibility = PXUIVisibility.SelectorVisible, Enabled = true)]
        [AutoNumber(typeof(PSSetup.numberingID), typeof(AccessInfo.businessDate))]
        [PXSelector(
            typeof(PSImport.importID),
            typeof(PSImport.description),
            typeof(PSImport.fileFormat),
            typeof(PSImport.status),
            typeof(PSImport.description)
        )]
        public virtual string ImportID { get; set; }
        public abstract class importID : PX.Data.BQL.BqlString.Field<importID> { }
        #endregion

        #region Description
        [PXDBString(IsUnicode = true, IsFixed = false)]
        [PXUIField(DisplayName = "Description")]
        public virtual string Description { get; set; }
        public abstract class description : PX.Data.BQL.BqlString.Field<description> { }
        #endregion

        #region File Format
        [PXDBString(2, IsFixed = true, IsUnicode = true)]
        [PXUIField(DisplayName = "File Format", Enabled = true)]
        [PXDefault]
        [PXStringList(
            new string[]
            {
                FileFormatTypes.Flats,
                FileFormatTypes.IDOA,
                FileFormatTypes.MMS,
                FileFormatTypes.OCR,
                FileFormatTypes.Pressero
            },
            new string[]
            {
                FileFormatTypeDisplayNames.Flats,
                FileFormatTypeDisplayNames.IDOA,
                FileFormatTypeDisplayNames.MMS,
                FileFormatTypeDisplayNames.OCR,
                FileFormatTypeDisplayNames.Pressero
            }
        )]
        public virtual string FileFormat { get; set; }
        public abstract class fileFormat : PX.Data.BQL.BqlString.Field<fileFormat> { }
        #endregion

        #region Status
        [PXDBString(2, IsFixed = true, IsUnicode = true)]
        [PXUIField(DisplayName = "Status", Enabled = false)]
        [PXDefault(ImportStatusTypes.Unvalidated)]
        [PXStringList(
            new string[]
            {
                ImportStatusTypes.Unvalidated,
                ImportStatusTypes.Invalid,
                ImportStatusTypes.Valid,
                ImportStatusTypes.Released
            },
            new string[]
            {
                ImportStatusTypeDisplayNames.Unvalidated,
                ImportStatusTypeDisplayNames.Invalid,
                ImportStatusTypeDisplayNames.Valid,
                ImportStatusTypeDisplayNames.Released
            }
        )]
        public virtual string Status { get; set; }
        public abstract class status : PX.Data.BQL.BqlString.Field<status> { }
        #endregion

        #region Date Imported
        [PXDBDate]
        [PXUIField(DisplayName = "Date Imported", Enabled = false)]
        public virtual DateTime? DateImported { get; set; }
        public abstract class dateImported : PX.Data.BQL.BqlDateTime.Field<dateImported> { }
        #endregion

        #region Date of Last Validation
        [PXDBDate]
        [PXUIField(DisplayName = "Date of Last Validation", Enabled = false)]
        public virtual DateTime? DateOfLastValidation { get; set; }
        public abstract class dateOfLastValidation : PX.Data.BQL.BqlDateTime.Field<dateOfLastValidation> { }
        #endregion

        #region Date Released
        [PXDBDate]
        [PXUIField(DisplayName = "Date Released", Enabled = false)]
        public virtual DateTime? DateReleased { get; set; }
        public abstract class dateReleased : PX.Data.BQL.BqlDateTime.Field<dateReleased> { }
        #endregion
    }

这是其中一个子 DAC(现在我只有钥匙,因为我还不知道我需要的所有字段,我只是想开始设计屏幕):

public class PSTranFlats : IBqlTable
{
    #region Import ID
    [PXDBString(15, IsKey = true, IsUnicode = true, InputMask = "")]
    [PXDBDefault(typeof(PSImport.importID))]
    [PXParent(typeof(SelectFrom<PSImport>.
        Where<PSImport.importID.IsEqual<PSTranFlats.importID.FromCurrent>>)
    )]
    public virtual string ImportID { get; set; }
    public abstract class importID : PX.Data.BQL.BqlString.Field<importID> { }
    #endregion
}

这是我设置的 DAC:

    [PXPrimaryGraph(typeof(PSSetupMaint))]
    public class PSSetup : IBqlTable
    {
        #region NumberingID
        [PXDBString(10, IsUnicode = true)]
        [PXDefault("PSIMPORT")]
        [PXUIField(DisplayName = "Import Numbering Sequence")]
        [PXSelector(typeof(Numbering.numberingID), DescriptionField = typeof(Numbering.descr))]
        public virtual string NumberingID { get; set; }
        public abstract class numberingID : PX.Data.BQL.BqlString.Field<numberingID> { }
        #endregion
    }

这是我的设置图:

    public class PSSetupMaint : PXGraph<PSSetupMaint>
    {
        #region Selects / Views

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

        public SelectFrom<PSSetup>.View Setup;

        #endregion
    }

这是我的主图:

    public class PSImportEntry : PXGraph<PSImportEntry>
    {
        #region Selects / Views
        public PXCancelClose<PSImport> CancelClose;
        public PXSaveClose<PSImport> SaveClose;
        public PXSave<PSImport> Save;
        public PXCancel<PSImport> Cancel;
        public PXInsert<PSImport> Insert;
        public PXDelete<PSImport> Delete;
        public PXFirst<PSImport> First;
        public PXPrevious<PSImport> Previous;
        public PXNext<PSImport> Next;
        public PXLast<PSImport> Last;

        public PXSetup<PSSetup> PSSetup;

        public SelectFrom<PSImport>.View Import;

        [PXImport(typeof(PSTranFlats))]
        public SelectFrom<PSTranFlats>.
            Where<PSTranFlats.importID.IsEqual<PSImport.importID.FromCurrent>>.View
            FlatsTransactions;

        [PXImport(typeof(PSTranIDOA))]
        public SelectFrom<PSTranIDOA>.
            Where<PSTranIDOA.importID.IsEqual<PSImport.importID.FromCurrent>>.View
            IDOATransactions;

        [PXImport(typeof(PSTranMMS))]
        public SelectFrom<PSTranMMS>.
            Where<PSTranMMS.importID.IsEqual<PSImport.importID.FromCurrent>>.View
            MMSTransactions;

        [PXImport(typeof(PSTranOCR))]
        public SelectFrom<PSTranOCR>.
            Where<PSTranOCR.importID.IsEqual<PSImport.importID.FromCurrent>>.View
            OCRTransactions;

        [PXImport(typeof(PSTranPressero))]
        public SelectFrom<PSTranPressero>.
            Where<PSTranPressero.importID.IsEqual<PSImport.importID.FromCurrent>>.View
            PresseroTransactions;

        #endregion
    }

我不是 100% 确定,但我认为这是关于 ASPX 中的 ID 而不是数据库数据。例如:

请注意该示例中的 ID="PXLayoutRule1"。如果 ASPX 中任何条目的此“ID”值在屏幕的任何位置被复制为另一个条目的 ID,您将收到错误消息。

我在早期版本中遇到过类似问题,尤其是当我尝试自定义屏幕时,自定义屏幕界面在中间崩溃了。我会尝试删除屏幕,但我会在 CstDesigner 和 CstPublished 文件夹中得到孤立的文件,这会使我的问题更加复杂。

希望您知道如何查看 ASPX 文件和自定义项目 XML 以检查所有 ID。如果您确实知道如何完成所有这些操作,只需在所有 ID 值中添加一些内容,例如在末尾添加 X。 (即 PXLayoutRule1X)如果没有,获得熟悉度是值得的 - objective 当您继续时。

如果您的问题与我过去遇到的相同,并且您不能简单地在 ASPX 文件或项目中找到并编辑重复的 ID XML,请采取以下步骤 在备份项目和这些步骤中记录的受影响的文件夹 之后。当然,这还假定您正在使用实例的开发副本。 (如果我不确定,我经常将我的主要 DEV 实例克隆到我的笔记本电脑上进行测试,这样我的 DEV 实例就不会受到影响。这只是需要额外的时间,你可能有也可能没有。)

  1. 从自定义项目中删除屏幕。
  2. 在您实例的根文件夹(即您的站点所在的 AcumticaDEV、Sandbox 等)下找到文件夹 CstDesigner 和 CstPublished
  3. 进入 Pages_XX 文件夹(其中 XX 是屏幕 ID 的前 2 个字母的 2 个字符代码)
  4. 如果找到屏幕文件,请从那里删除它们。
  5. 如果这是自定义屏幕,请进入与步骤 2 中的那些文件夹位于实例根文件夹中的 Pages 文件夹,然后在该文件夹中重复步骤 3 和 4。
  6. 从自定义项目屏幕的文件菜单中检查项目 XML 中是否有任何对您的屏幕的引用,如果存在这些部分,请将其删除。 (这往往与自定义现有屏幕有关。)
  7. 发布您的项目。
  8. 在您的页面上重新开始,看看您是否仍然遇到错误。

同样,请务必在执行这些步骤之前进行备份,以便在无法解决您的问题时轻松将其放回原处。