Dynamics AX Blog

Eintrag "RPC exception 1702 occurred" im Eventlog

Object Server 01:  RPC error: RPC exception 1702 occurred in session 4 process is Ax32Serv.exe thread is 8788(User: admin, ClientType: Worker)

Dieser Eintrag kann auf die Verwendung von client-seitigem Code am Server hindeuten, beispielsweise den Aufruf einer WinApi-Funktion aus einem Stapeljob heraus.

Sie kann aber auch durch den Aufruf von info(), Warning() oder error() innerhalb eines Stapeljobs ausgelöst werden, wenn am jeweiligen AOS die Option "Enable global breakpoint" aktiviert ist.

Screenshot AX 2012 Server Configuration Utility


 
 
 

SQL-Fehler beim Synchronisieren nach Update von AX 2012 auf CU13

Während des Upgrades einer AX 2012 R3 CU9-Instanz auf CU13 (February Release) hatte ich beim Punkt Datenbank synchronisieren der Upgrade-Checklist folgenden Fehler:

SQL error description: [Microsoft][SQL Server Native Client 11.0][SQL Server]The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'dbo.LEDGERPERIODMODULEACCESSCONTROL' and the index name 'I_7375LEDGERFISCALCALENDARPERIODIDX'. The duplicate key value is (5637144576, 22565421332).

SQL statement: CREATE UNIQUE  INDEX I_7375LEDGERFISCALCALENDARPERIODIDX ON "DBO".LEDGERPERIODMODULEACCESSCONTROL (PARTITION,LEDGERFISCALCALENDARPERIOD)

Die Lösung ist, diesen fehler fürs erste so zu belassen und mit dem nächsten Schritt der Checklist, dem Data upgrade zu starten. Einer der auszuführenden Jobs bereinigt nämlich jene Datensätze, die zu dem genannten Fehler führen.

Nach dem Datenupgrade kann man nun die Datenbank fehlerfrei synchronisieren.

Screenshot
 


 
 
 

SysOperation-Framework: ExecutionMode und auszuführende Servermethode über das MenuItem steuern

Wenn man in einem SysOperation-Konstrukt den SysOperationExecutionMode und/oder die auszuführende Servermethode über das MenuItem steuern möchte, kann man dies über die Eigenschaften des MenuItems steuern.

Szenario: Ohne eigenen Controller

Die folgenden beiden MenuItems zeigen, wie man dafür die Eigenschaften setzen kann:

Dieses MenuItem ruft die Methode runService() einer Serviceklasse auf und setzt den SysOperationExecutionMode auf Synchronous:

Screenshot


 
 
 

SysOperation-Framework: Stapelverarbeitung erzwingen

Wenn man sicherstellen möchte, daß eine Funktion die über das SysOperation-Framework umgesetzt wurde, immer über die Stapelverarbeitung ausgeführt wird, kann man den SysOperationExecutionMode auf ScheduledBatch setzen (beispielsweise über das MenuItem des Controllers - siehe hier).

Handelt es sich dabei um eine Funktion, die einen Benutzerdialog erfordert, hat man allerdings das Problem, daß standardmässig der Register "Stapel" eingeblendet wird und dort aber beispielsweise das Kontrollkästchen Stapel nicht aktiviert ist. 

Natürlich kann man dieses Kontrollkästchen nun aktivieren, in dem man einen Aufruf von parmBatchExecute() im UIBuilder integriert:

public void build()
{
    super();

    this.controller().batchInfo().parmBatchExecute(this.controller().parmExecutionMode() == SysOperationExecutionMode::ScheduledBatch);
}

 
 
 

Erstellen und Buchen einer Freitextrechnung per Code

Der nachstehende Job soll zeigen, wie man per Code eine Freitextrechnung erstellen und buchen kann.

static void createAndPostFreeTextInvoice(Args _args)
{
    CustInvoiceTable custInvoiceTable;
    CustInvoiceLine custInvoiceLine;
    DimensionDefault dimensionDefault; 
    LedgerDimensionAccount ledgerDimensionAccount;     
    CustPostInvoice custPostInvoice;
    
    try
    {
        ttsBegin;        
        
        // Create header
        custInvoiceTable.clear();
        custInvoiceTable.initValue();
        custInvoiceTable.OrderAccount = "US-004";
        custInvoiceTable.modifiedField(
            fieldNum(CustInvoiceTable, OrderAccount));
        custInvoiceTable.insert();
        
        // Create line
        custInvoiceLine.clear();
        custInvoiceLine.initValue();
        custInvoiceLine.ParentRecId = custInvoiceTable.RecId;
        custInvoiceLine.initFromCustInvoiceTable(custInvoiceTable);
        custInvoiceLine.Description = "Test";
        custInvoiceLine.Quantity = 10;
        custInvoiceLine.modifiedField(
            fieldNum(CustInvoiceLine, Quantity));
        custInvoiceLine.UnitPrice = 200;
        custInvoiceLine.modifiedField(
            fieldNum(CustInvoiceLine, UnitPrice));
        
        ledgerDimensionAccount = 
        DimensionDefaultingService::serviceCreateLedgerDimension(
            DimensionStorage::getDefaultAccountForMainAccountNum(
                "110110"), 
                dimensionDefault); 
        
        custInvoiceLine.LedgerDimension = ledgerDimensionAccount;
        custInvoiceLine.modifiedField(
            fieldNum(CustInvoiceLine, LedgerDimension));
        custInvoiceLine.insert();
        
        // Post
        custPostInvoice = new CustPostInvoice(custInvoiceTable);
        custPostInvoice.run();
        
        ttsCommit;
    }
    catch
    {
        throw error(error::wrongUseOfFunction(funcName()));
    }
}

So sieht eine wie oben erstellte Freitextrechnung aus:

Screenshot Freetext invoice


 
 
 

Debuggen von SSRS-Dataprovider die von SrsReportDataProviderPreProcess abgeleitet sind

In diesem Beitrag habe ich schon einmal beschrieben, wie man einen DataProvider "debuggen" kann, der von SRSReportDataProviderBase abgeleitet ist. 

Der folgende Job macht prinzipiell das gleiche, allerdings für vorverarbeitete Reports, also welche wo der DataProvider von SrsReportDataProviderPreProcess abgeleitet ist. Im Beispiel verwende ich den DataProvider einer Ausgangsrechnung (SalesInvoice).

static void testSSRSDataProvider_SalesInvoice(Args _args)
{
    SalesInvoiceTmp salesInvoiceTmp;
    SalesInvoiceDP dataProvider = new SalesInvoiceDP();
    SalesInvoiceContract contract;
    CustInvoiceJour CustInvoiceJour = CustInvoiceJour::findRecId(35637191172);
    UserConnection UserConnection;

    try
    {
        ttsBegin;

        UserConnection = new UserConnection();

        contract = new SalesInvoiceContract();
        contract.parmFormLetterRecordId(CustInvoiceJour.RecId);
        contract.parmRecordId(CustInvoiceJour.RecId);

        dataProvider = new SalesInvoiceDP();
        dataProvider.parmDataContract(contract);
        dataProvider.parmUserConnection(UserConnection);
        dataProvider.processReport();

        salesInvoiceTmp = dataProvider.getSalesInvoiceTmp();
        
        while select salesInvoiceTmp
            where SalesInvoiceTmp.createdTransactionId == appl.curTransactionId()
        {
            info(strFmt("%1 %2", SalesInvoiceTmp.InvoiceId, SalesInvoiceTmp.ItemId));
        }

        ttsCommit;
    }
    catch (Exception::Break)
    {
        info("Aborted");
    }
}

 


 
 
 

Entnahme einer reservierten Auftragsposition per Code

Um die bereits reservierten Mengen einer Auftragspositionen per Code zu entnehmen, kann man Code wie den folgenden verwenden:

static void JobPick(Args _args)
{
    Query inventTransQuery;
    QueryRun qr;
    QueryBuildDataSource qbds;
    InventTrans inventTrans;
    InventDim inventDim;
    InventTransOrigin inventTransOrigin;
    TmpInventTransWMS tmpInventTransWMS;
    InventTransWMS_Pick inventTransWMS_Pick;
    SalesLine salesLine = SalesLine::findInventTransId('014417');
    
    inventTransQuery = new Query();
    qbds = inventTransQuery.addDataSource(tableNum(InventTrans));
    qbds.addRange(fieldNum(InventTrans, StatusIssue)).value(queryValue(StatusIssue::ReservPhysical));
    qbds = qbds.addDataSource(tableNum(InventTransOrigin));
    qbds.relations(true);
    qbds.joinMode(JoinMode::InnerJoin);
    qbds.addRange(fieldNum(InventTransOrigin, InventTransId)).value(salesLine.InventTransId);
    
    qr = new QueryRun(inventTransQuery);
    while (qr.next())
    {
        inventTrans = qr.get(tableNum(InventTrans));
        inventTransOrigin = qr.get(tableNum(InventTransOrigin));
        
        // Set inventory dimensions for picking
        inventDim = inventDim::find(inventTrans.InventDimId);
        inventDim.wmslocationId = "06A01R3S1B";   
        inventDim.LicensePlateId = "LP_61_A0001";
        inventDim = inventDim::findOrCreate(inventDim);
        
        tmpInventTransWMS.clear();
        
        inventTransWMS_Pick = InventTransWMS_Pick::newStandard(tmpInventTransWMS, inventTransQuery);
        
        tmpInventTransWMS.initFromInventTrans(InventTrans);
        tmpInventTransWMS.initFromInventTransOrigin(inventTransOrigin);
        tmpInventTransWMS.initFromInventDim(inventDim);
        
        tmpInventTransWMS.InventQty = -inventTrans.Qty;
        
        inventTransWMS_Pick.writeTmpInventTransWMS(tmpInventTransWMS);
        inventTransWMS_Pick.updateInvent();    
    }
}

 
 
Seiten 1 2 3 4 ... 52 » 

 

 
 
 
Beiträge des aktuellen Monats
Oktober 2019
MoDiMiDoFrSaSo
 123456
78910111213
14151617181920
21222324252627
28293031 
 
© 2006-2019 Heinz Schweda | Impressum | Kontakt | English version | Mobile Version
Diese Webseite verwendet Cookies, um Benutzern einen besseren Service anzubieten. Wenn Sie weiterhin auf der Seite bleiben, stimmen Sie der Verwendung von Cookies zu.  Mehr dazu