Acumatica-已添加/更新了另一个过程记录-使用DAC和图形扩展创建库存物料

时间:2018-09-20 19:42:27

标签: c# acumatica

我正在尝试创建一个每天运行的流程,该流程将从另一个数据库中导入记录作为“库存物品”。为此,我需要创建InventoryItemMaint图的扩展(给我自定义操作),以及InventoryItem DAC的扩展(给我自定义字段)。我试图遵循T-300手册中明确规定的准则进行操作。

这是我的InventoryItemMaint扩展的代码:

    namespace PX.Objects.IN
{

  public class InventoryItemMaint_Extension:PXGraphExtension<InventoryItemMaint>
  {

    public PXAction<PX.Objects.IN.InventoryItem> DailyOnixImport;

        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Daily Onix Import")]
        protected void dailyOnixImport()
        {           
            var invItemMaintExtInstance = Base.GetExtension<InventoryItemMaint_Extension>();

            string todaysDate = DateTime.Today.ToString("MM/dd/yyyy");                        

            foreach (STOnixItem currentOnixItem in PXSelect<STOnixItem,
                        Where<STOnixItem.addedDate, Equal<Required<STOnixItem.addedDate>>>>
                        .Select(this.Base, todaysDate))
            {                                
                InventoryItem currentInventoryItem = invItemMaintExtInstance.Base.Item.Current;

                PXCache inventoryItemCache = invItemMaintExtInstance.Base.Item.Cache;
                InventoryItemExt inventoryItemExtension = inventoryItemCache.GetExtension<InventoryItemExt>(currentInventoryItem);

                inventoryItemCache.Clear();

                currentInventoryItem.InventoryCD = currentOnixItem.ISBN13;                

                currentInventoryItem.Descr = currentOnixItem.Title;
                currentInventoryItem.ItemClassID = currentOnixItem.ItemClass;
                currentInventoryItem.RecPrice = decimal.Parse(currentOnixItem.MSRP);
                currentInventoryItem.BasePrice = decimal.Parse(currentOnixItem.DefaultPrice);
                currentInventoryItem.BaseItemWeight = decimal.Parse(currentOnixItem.Weight);
                currentInventoryItem.WeightUOM = "POUND";
                currentInventoryItem.ImageUrl = currentOnixItem.ImageLink;

                //Assigning to the custom DAC Extension
                inventoryItemExtension.UsrFromOnixFile = currentOnixItem.FromFile;

                inventoryItemCache.Update(currentInventoryItem);
                Base.Actions.PressSave();

            }
        }
  }
}

我目前收到一条错误消息:

  

错误:另一个进程已更新'InventoryItem'记录。您的   更改将丢失。

这是错误跟踪文本:

  

9/20/2018 3:26:05 PM错误:错误:另一个进程添加了   “ InventoryItem”记录。您的更改将丢失。

     

位于PX.Data.PXCache 1.PersistInserted(Object row) at PX.Data.PXCache 1.Persist(位于PXDBOperation操作)   PX.Data.PXGraph.Persist(类型cacheType,PXDBOperation操作)
  在PX.Data.PXGraph.Persist()在   PX.Objects.IN.InventoryItemMaint.Persist()在   PX.Data.PXSave 1.d__2.MoveNext() at PX.Data.PXAction 1.d__31.MoveNext()在   PX.Data.PXAction 1.d__31.MoveNext() at PX.Data.PXActionCollection.PressSave(PXAction caller) at PX.Objects.IN.InventoryItemMaint_Extension.dailyOnixImport() at PX.Data.PXAction 1。<> c__DisplayClass3_0。<。ctor> b__0(PXAdapter适配器)   在PX.Data.PXAction 1.a(PXAdapter A_0) at PX.Data.PXAction 1.d__31.MoveNext()在   PX.Data.PXAction`1.d__31.MoveNext()在   PX.Web.UI.PXBaseDataSource.tryExecutePendingCommand(String viewName,   String [] sortcolumns,Boolean []降序,Object []搜索,   Object []参数,PXFilterRow []过滤器,DataSourceSelectArguments   参数,Boolean&closeWindowRequired,Int32&adapterStartRow,   Int32&adapterTotalRows)位于   PX.Web.UI.PXBaseDataSource.ExecuteSelect(String viewName,   DataSourceSelectArguments参数,PXDSSelectArguments pxarguments)

我已经在StackOverflow和其他地方进行了很多搜索,但是还没有找到似乎完全可以解决我的问题的答案。我所做的调整导致了其他错误,例如我现在所获取内容的变化(添加了另一个过程而更新了另一个过程)和MoveNext错误。

如果有人能够帮助我,我将非常感激。

4 个答案:

答案 0 :(得分:0)

代码中似乎存在逻辑缺陷。您正在循环更新同一当前对象。这毫无用处,因为它将始终用循环返回的最后一项覆盖。如果您不小心,则循环调用“保存”操作也会导致错误。

正如我在评论中提到的,清除缓存似乎是错误的。您想将当前数据保留在那里。当您调用clear时,您将使图形的主要文档失效,这将导致错误。

与InventoryCD之类的键紧密相关的更改字段可能会导致文档被清除和无效。如果您必须考虑插入新记录而不是更新当前记录来修改关键字段。

我建议您进行其他更改。

代码:

// Consider replacing the default namespace to avoid conflicts
namespace MyNamespace
{
  public class InventoryItemMaint_Extension:PXGraphExtension<InventoryItemMaint>
  {
    public PXAction<PX.Objects.IN.InventoryItem> DailyOnixImport;

    // '(CommitChanges = true)' is not necessary
    [PXButton]
    [PXUIField(DisplayName = "Daily Onix Import")]
    protected void dailyOnixImport()
    {           
      InventoryItemMaint_Extension invItemMaintExtInstance = Base.GetExtension<InventoryItemMaint_Extension>();

      string todaysDate = DateTime.Today.ToString("MM/dd/yyyy");                        

      // You need to rethink that 'foreach' logic
      STOnixItem currentOnixItem in PXSelect<STOnixItem,
                                    Where<STOnixItem.addedDate, Equal<Required<STOnixItem.addedDate>>>>.Select(Base, todaysDate);    

      // You can access Base directly, no need to fetch it from the extension
      InventoryItem currentInventoryItem = Base.Item.Current;

      // Consider using more null check
      if (currentOnixItem != null && currentInventoryItem != null)
      {
        // Consider using similar names for similar variables
        InventoryItemExt currentInventoryItemExt = currentInventoryItem.GetExtension<InventoryItemExt>();

        // Avoid setting key related fields like InventoryCD when updating
        currentInventoryItem.Descr = currentOnixItem.Title;
        currentInventoryItem.ItemClassID = currentOnixItem.ItemClass;
        currentInventoryItem.RecPrice = decimal.Parse(currentOnixItem.MSRP);
        currentInventoryItem.BasePrice = decimal.Parse(currentOnixItem.DefaultPrice);
        currentInventoryItem.BaseItemWeight = decimal.Parse(currentOnixItem.Weight);
        currentInventoryItem.WeightUOM = "POUND";
        currentInventoryItem.ImageUrl = currentOnixItem.ImageLink;

        currentInventoryItemExt.UsrFromOnixFile = currentOnixItem.FromFile;

        // You fetched the item from the DataView 
        // you can update it in the DataView too.
        Base.Item.Update(currentInventoryItem);

        // Is it really needed to save here?
        // This coupled with cache clearing and the loop updating 
        // the same record triggers the error in your question.
        Base.Actions.PressSave();
      }
    }
  }
}

答案 1 :(得分:0)

伙计们, 当我们尝试更新DAC中的复杂字段之一时,我在EmployeeMaint中遇到了相同的异常。

enter image description here

即使在保存之前没有代码运行,

baseAction()也会引发此异常。 我遵循了您的建议@HuguesBeauséjour,发现原因可能是: enter image description here

意味着,缓存已脏。 因此,要解决我的问题,我只需要清除引发异常的对象的缓存。 在我的情况下,例外是:

Update employee class error - Another process has added the 'VendorPaymentMethodDetail' record. Your changes will be lost

所以我需要清除VendorPaymentMethodDetail的缓存:

Base.Caches<VendorPaymentMethodDetail>().Clear();

在清除高速缓存后,需要在代码期间从高速缓存中读取数据时,请小心清除高速缓存。在这种情况下,您需要在清理之前从缓存中复制对象,然后再使用此副本。

希望对某人有帮助。

答案 2 :(得分:0)

我发现了另一个可能导致相同异常的原因: enter image description here

当您从不同缓存中的同一表中进行选择时,可能会发生这种情况,其中一个用于选择,另一个用于插入。例如:

我们有一个观点:

 public PXSelect<MPEmployeeWorkSchedule, Where<MPEmployeeWorkSchedule.employeeID, Equal<Current<MPEmployeeTermination.employeeID>>>> EmployeeWorkSchedule;

并且在事件中我们有代码段: enter image description here 我们使用与上面的视图相同的DAC,然后将其插入视图:

EmployeeWorkSchedule.Cache.Insert(workSchedule);

然后Persist()引发异常。

解决方案再次是创建另一个视图而不是查询并清除缓存: enter image description here enter image description here

我希望这会有所帮助。

答案 3 :(得分:0)

想分享另一种查找相同错误消息的方法。就我而言,问题出在数据库结构上。 为了修复错误消息,我执行了以下步骤:

  1. 掉了我的桌子
  2. 从现有表生成 sql 脚本
  3. 删除了不需要的列
  4. 复制/粘贴现有​​列,并替换名称

结果,我的错误消息消失了。