Hi people,
I'm building a RDP based SSRS report and I'm facing an issue.
In my DP class, I use 2 table to get my data (classical Header + Lines). The problem is if I set my both table as temp table or both as Regular, my report is not displaying all datas. If I set 1 table as temp and the other as regular, everythink is working fine.
My questions are :
Is it possible to use 2 temp table with a RDP extending SRSReportDataProviderBase ? (prefered solution, easier and faster to build)
Or do I need to extend SrsReportDataProviderPreProcess and manage this with regular table and transId as SalesOrderReport for exemple ?
thank you for you advice,
Stek
AX 2012 R2
No problem.
Working with temporary tables is a bit confusing, because it looks almost the same as with regular tables but it actually works in quite a different way.
If you insert data to a regular table, everybody can see it. All you need to know to query the data is the table name. You ask the DB server for the content of the table, and the server returns it to you.
If you insert data to a temporary table, you get a completely new container for data (a memory location, a file on disk or a new table in TempDB database). And the variable in X++ holds a reference to this container. Nobody can access the data without this reference.
If you create two variables for VendorReminderLineTmp table, you have to separate containers. If you insert a record to one buffer, you want see it in the other buffer, because they point to different memory locations, files or TempDB tables. An exception is if you explicitly make them point to the same container. In your own code, you use setTmpData() (for InMemory tables) or linkPhysicalTableInstance() (for TempDB tables). Then you can insert data to either buffer and you can retrieve it from both.
This is also what happens with RecordInsertList. You're giving it a refer to a temporary data set that the class should use, instead of using a new independent one.
I've edited my previous message, I forgot to refresh some caches, it works fine with Insert().
Plus, I followed your advice to use the 7th argument in construct of RecordInsertList and that totally works !
recInsList = new RecordInsertList( tableNum(DLZvendorReminderLineTmp), false, false, false, false, false, vendorReminderLineTmp);
Thank you for precision about RecordInsertList. Last question, I promise. I dont really understand why this 7th argument is necessary ? What's different with a Regular table that make this argument required ?
Anyway, thank you very much Martin for your precious time and your help.
Can you show your current code? How do you test it? The statement that the kernel of AX is broken and insert() method doesn't work at all on temporary tables doesn't sound likely.
The assumption that RecordInsertList always reduces the number of DB calls isn't precise. In certain cases, it still processes records one by one (if insert() method is overriden, InMemory table is used and so on). Therefore checking if there is any benefit still makes sense.
For completeness, RecordInsertList often makes more than just one DB call - it would require holding all records in memory. Instead, it inserts records in batches.
I dont get it. What's wrong with RecordInsertList ? I've always used it this way.
But anyway, the problem persist even if I use simple Insert().
Ok after cleaning all cache, restart AOS and SSRS, it's seems that it's working while inserting record by record.
My new questions are :
Does TempDB / InMemory table support RecordInsertList ?
Is my utilisation of RecordInsertList correct ? If yes, how can I identify in the future that's RecordInsertList causing problem ? (refering to the fact that worked with regular table)
[quote]whether using RecordInsertList has any benefit in this case.[/quote]Just going for a single trip database insert so it's a benefit, no ?
Both types (InMemory and TempDB) should work, but it's good to know which case we're discussion.
I think the problem is related to the RecordInsertList. You return data from vendorReminderLineTmp buffer, but you've never inserted anything there. You just use the variable to provide input for RecordInsertList.
Maybe it can be done by passing the temporary buffer to the 7th argument of RecordInsertList's constructor, but I would first ask myself whether using RecordInsertList has any benefit in this case.
I tried with InMemory too but actualy, I confirm using tempDB.
Hmm, so you're now using TempDB tables? Can you please confirm whether you're using only TempDB tables (not InMemory temporary tables) from the beginning?
Here is my DP simplified as much as possible.
[ SRSReportQueryAttribute(queryStr(PurchLineBackOrder)), SRSReportParameterAttribute(classstr(DLZvendorReminderContract)) ] class DLZvendorReminderDP extends SRSReportDataProviderBase { DLZvendorReminderContract contract; DLZvendorReminderLineTmp vendorReminderLineTmp; DLZvendorReminderHeaderTmp vendorReminderHeaderTmp; Query q; VendAccount vendId; DlvDate delayDate, projectedDelayDate; }
[ SRSReportDataSetAttribute(tableStr(DLZvendorReminderHeaderTmp)) ] public DLZvendorReminderHeaderTmp getDLZVendorReminderHeaderTmp() { select vendorReminderHeaderTmp; return vendorReminderHeaderTmp; } [ SRSReportDataSetAttribute(tableStr(DLZvendorReminderLineTmp)) ] public DLZvendorReminderLineTmp getDLZVendorReminderLineTmp() { select vendorReminderLineTmp; return vendorReminderLineTmp; }
[ SysEntryPointAttribute(false) ] public void processReport() { this.setDataTest(); } public void setDataTest() { RecordInsertList recInsList; int i; // HEADER vendorReminderHeaderTmp.clear(); vendorReminderHeaderTmp.ReminderID = 'ReminderID'; vendorReminderHeaderTmp.ReminderDate = today(); vendorReminderHeaderTmp.CompanyName = 'CompanyName'; vendorReminderHeaderTmp.CompanyAddress = 'CompanyAddress'; vendorReminderHeaderTmp.CompanyPhone = 'CompanyPhone'; vendorReminderHeaderTmp.CompanyTeleFax = 'CompanyTeleFax'; vendorReminderHeaderTmp.CompanyEmail = 'CompanyEmail'; vendorReminderHeaderTmp.CompanyURL = 'CompanyURL'; vendorReminderHeaderTmp.CompanyCoRegNum = 'CompanyCoRegNum'; vendorReminderHeaderTmp.CompanyEnterpriseNumber = 'CompanyEnterpriseNumber'; vendorReminderHeaderTmp.PrintLogo = NoYes::No; vendorReminderHeaderTmp.CompanyContactName = 'CompanyContactName'; vendorReminderHeaderTmp.VendorContactName = 'VendorContactName'; vendorReminderHeaderTmp.VendName = 'VendName'; vendorReminderHeaderTmp.VendAddress = 'VendAddress'; vendorReminderHeaderTmp.IntroMessage = 'IntroMessage'; vendorReminderHeaderTmp.OutroMessage = 'OutroMessage'; vendorReminderHeaderTmp.insert(); // LINES recInsList = new RecordInsertList(tableNum(DLZvendorReminderLineTmp)); for (i = 1; i <= 20; i ) { vendorReminderLineTmp.clear(); vendorReminderLineTmp.PurchId = strFmt('PurchId %1', i); vendorReminderLineTmp.LineNumber = i; vendorReminderLineTmp.ItemId = strFmt('ItemId %1', i); vendorReminderLineTmp.InventDimStr = 'InventDimStr'; vendorReminderLineTmp.ItemNameAlias = 'ItemNameAlias'; vendorReminderLineTmp.ExternalItemNum = 'ExternalItemNum'; vendorReminderLineTmp.QtyOrdered = i; vendorReminderLineTmp.RemainPurchPhysical = i; vendorReminderLineTmp.PurchUnit = 'PurchUnit'; vendorReminderLineTmp.DeliveryDate = today(); vendorReminderLineTmp.ConfirmedDlv = today(); vendorReminderLineTmp.DLZPurchLineDelayStatus = DLZPurchLineDelayStatus::Delay; recInsList.add(vendorReminderLineTmp); } recInsList.insertDatabase(); }
My both table are tempDB and here is my result:
What i expect: (1 tempDB 1 regular)
Sorry, I meant a report. All right, so now we know that the problem isn't anywhere in the report design, but it's in processReport(). Therefore you should debug processReport().
I noticed that the temp table which is not filled is random. Sometime it's the HeaderTable, sometimes it's the LinesTable. I really dont understand what's happening.
Here is a job I use to test my RDP. got the same problem when executing the job or the report. So the problem might be in my classes.
static void job11(Args _args) { DLZvendorReminderDP rdp; DLZvendorReminderContract contract; DLZvendorReminderHeaderTmp headerData; DLZvendorReminderLineTmp lineData; contract = new DLZvendorReminderContract(); contract.parmDelayDate(mkDate(14, 2, 2020)); contract.parmVendId('00005'); rdp = new DLZvendorReminderDP(); rdp.parmDataContract(contract); rdp.processReport(); headerData = rdp.getDLZVendorReminderHeaderTmp(); while select headerData { info(strFmt("%1 – %2", headerData.ReminderID, headerData.IntroMessage)); } lineData = rdp.getDLZVendorReminderLineTmp(); while select lineData { info(strFmt("%1 - %2", lineData.PurchId, lineData.LineNumber)); } info("fin"); }
Stay up to date on forum activity by subscribing. You can also customize your in-app and email Notification settings across all subscriptions.
André Arnaud de Cal... 291,240 Super User 2024 Season 2
Martin Dráb 230,104 Most Valuable Professional
nmaenpaa 101,156