-
On a database that is upgraded from AX 4.0 to AX 2009 running on SQL 2008 you may get following error while using database log:
The target table 'SYSDATABASELOG' of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause.. The SQL statement was:
INSERT INTO SYSDATABASELOG (DATA,USERNAME,DESCRIPTION,LOGTYPE,TABLE_,LOGRECID,CREATEDBY,CREATEDTRANSACTIONID, DATAAREAID,RECVERSION,RECID) OUTPUT INSERTED.CREATEDDATETIME VALUES (?,?,?,?,?,?,?,?,?,?,?)
To solve this issue you need to drop the onSYSDATABASELOGinsert trigger by executing this statement in SQL Server Management Studio:
USE <ax_database_name>;
GO
DROP TRIGGER [onSYSDATABASELOGinsert];
GO
You may also need to modify the default constraint for CreatedDateTime field to replace the default value ‘1900-01-01 00:00:00.000’ coming from AX 4.0 with ‘dateadd(millisecond, -datepart(millisecond,getutcdate()),getutcdate())’. To do this you can execute following code:
ALTER TABLE dbo.SYSDATABASELOG
DROP CONSTRAINT <constraint_name>
GO
ALTER TABLE dbo.SYSDATABASELOG ADD CONSTRAINT
<constraint_name> DEFAULT dateadd(millisecond, -datepart(millisecond,getutcdate()),getutcdate()) FOR CREATEDDATETIME
GO
Martin F
-
Sometimes you need to move your existing Demand Planner database to another server. If you do this just using backup/restore, you will run into the issue while synchronizing the Demand Planner. The error you get is:
Could not find ‘server name’ in sys.sysservers
This is because Demand Planner uses fully qualified object names in some stored procedures and functions, what results in original server name to be used.
Follow these steps to change the server name in existing functions and stored procedures:
1. Open SQL Server Management Studio and expand Databases
2. Right-click the Demand Planner database and select Tasks –> Generate Scripts
3. Click Next on the welcome screen
4. Select the Demand Planner database on Select Database screen and click Next.
Do not check the “Script all objects in the selected database” check box!
5. On the Choose Screen Options screen change value for Script Drop to True and click Next
6. On the Select Object Types screen select Stored procedures, Functions and Views and click Next
7. On the Choose Stored Procedures screen click Select All and then Next. Repeat this also to select all functions and views
8. On the Output Option screen keep the default selection and click Finish
9. On the summary page click Finish
10. In the query window press CTRL+H to open Find and replace window and type name of the original server into Find what field and name of the new server into Replace with field and click Replace All.
11. Press F5 to execute the script when all occurrences are replaced.
Now you should be able to synchronize Demand Planner.
Martin F
-
If you use this code, you will get an error on the line 29. The error message is following:
Cannot edit a record in Table1 (Table1).
An update conflict occurred due to another user process deleting the record or changing one or more fields in the record.
1: static void updateTable1(Args _args)
2: {
3: Table1 tbl;
4: ;
5:
6: ttsbegin;
7: select firstonly forupdate tbl;
8:
9: if (tbl.RecId)
10: {
11: tbl.InfoText = "Reset";
12: tbl.update();
13: }
14: else
15: {
16: tbl.InfoText = "Reset";
17: tbl.IntField = 1;
18: tbl.insert();
19: }
20: ttscommit;
21:
22: tbl.clear();
23:
24: select firstonly RecId, InfoText from tbl;
25:
26: ttsbegin;
27: tbl.selectForUpdate(true);
28: tbl.InfoText = "Table1 - field select";
29: tbl.update();
30: ttscommit;
31: }
The reason for this is that each time the table is updated the field RecVersion is updated with a random number that is saved by kernel. That why when you try to update the record, kernel cannot update record partly, what results in update conflict.
There are two ways to avoid this issue:
1. Add RecVersion field into the selection
24: select firstonly RecId, InfoText, RecVersion from tbl;
2. Use selectforupdate keyword
24: select firstonly forupdate RecId, InfoText from tbl;
Martin F
-
When you are calling Win API function (or function from a native DLL) on x64 you get this error:
An exception occurred when calling Function in Library name DLL library
This happens only if the code calling the DLL function is running on server. The reason for this is that the DLLFunction class is not supported on x64.
Martin F
-
You can get this error message while renaming object that is checked out from TFS.
Unable to import
Trying to import Table MFATable_test1 with ID 50003
ID already held by Table MFATable1
To rename the object you need to follow these steps:
- Right click the object in AOT and select Rename (without checking out the object)
- Type a new name of the object. New object with the new name will be created
- Select Tools –> Development tools –> Version control in AX menu and click Pending objects
- Check in both objects
To update all objects that reference the renamed object, you need to check out all objects that refer to the object you want to rename. When you rename an object, two copies of the object are created: one with the old name and one with the new name. When you check in these objects (for delete and add, respectively), the system integrates both objects to maintain the history.
Martin F
-
RTM version (5.0.593.0) of .NET Business Connect fails with following exception while creating instance of XmlDocument class in X++ code.
System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at AxCore_CallStatic(Char* , Char* , tagVARIANT* , Int32 , tagVARIANT* )
at Microsoft.Dynamics.BusinessConnectorNet.Axapta.CallStaticClassMethod(String className, String methodName, Object[] paramList)
at Microsoft.Dynamics.BusinessConnectorNet.Axapta.CallStaticClassMethod(String className, String methodName)
at BusinessLogic.DocumentationManager.GetXml() in D:\Development\AX\BC.NET Sample Test\BusinessLogic\DocumentationManager.cs:line 13
at ConsoleTest.Program.Main() in D:\Development\AX\BC.NET Sample Test\Console Test\Program.cs:line 15
To avoid this issue you need to install SP1 for AX 2009 (you need to have access to Partnersource).
Martin F
-
You might need to print Word document directly from X++. Here’s a short sample how to do this:
{
str document = "C:\\test.doc";
COM wordApplication;
COM wordDocuments;
COM wordDoc;
;
// Create instance of Word application
wordApplication = new COM("Word.Application");
// Get documents property
wordDocuments = wordApplication.Documents();
// Open document
wordDoc = wordDocuments.Open(document);
// Activate the document - this is necessary to print it
wordDoc.Activate();
// Print the document
wordDoc.PrintOut();
// Close document
wordDoc.Close();
// Close Word application
wordApplication.Quit();
}
Martin F
-
You may see similar error while posting ledger journal:
Posting - Journal
Journal: 000004_061
Voucher: 8004_062
Cannot select a record in ().
The SQL database has issued an error.
The journal is not posted and the update is canceled.
SQL error description: [Microsoft][SQL Native Client][SQL Server]Invalid object name '#ax_tmp_dmo3_52_0'.
This error is caused by collecting Query plans while doing SQL tracing. To avoid this error you need to disable Query plan collection in Tools | Options on SQL tab.
Martin F
-
Sometimes you need to import addresses into AX 2009 and enable RecID compression. This import might result in an error:
Update of RecID-key xxxxxxxx failed for the register DirPartyAddressRelationshipMapping.
To solve this you need to follow these steps:
- Restore the database
- Disable RecID unique index on the table affected by this issue
- Synchronize
- Import data
- Enable RecID unique index
- Synchronize
Martin F
-
You may want to load an image from base64 coded string. Then there is a code sample how to achieve it. First is needed to put an "Window" controll on the form with name ex. "imageWindow" and then modify "run()" method of Form. String then could be loaded from database, generated by .NET (for example dynamicaly generate picture) etc.
public void run()
{
container baseContainer;
BinData binData;
Image img;
;
super();
// create container from base64
baseContainer = BinData::loadFromBase64(".... BASE64 STRING....");
// create bindata from container.
binData = new BinData();
binData.setData(baseContainer);
// lock element
element.lock();
// create Image from bindata
img = new Image();
img.setData(binData.getData());
// show and update image.
imageWindow.image(img);
imageWindow.widthValue(img.width());
imageWindow.heightValue(img.height());
imageWindow.update();
// unlock elements.
element.resetSize();
element.unLock();
}
Karel F
-
I was facing an issue that no mails were arrived while sending invoices in PDF from a batch. Sending e-mails from a client worked fine. The reason is in enabled SMTP relaying on customer's mail server and in \Classes\RunbaseReportStd\serverSendMail method. This method calls quickSend() method from SysMailer class. The first parameter of this method is fromAddress. In this method this parameter is filled with same value as toAddress. This may cause that no mail will be delivered when SMTP server is configured to drop relayed mails.
Martin F
-
You might need to execute an external process in a batch and you’re thinking about using WinApi::shellExecute() method. Unfortunately the whole WinApi class is set to run on client. Also the method WinApi::shellExecute() is marked as client method. That why you can’t use this method to execute an external process from batch. How to execute external process then? One option is to use System.Diagnostics.Process .NET class. Here’s a short sample how to use System.Diagnostics.Process to execute an external process:
{
System.Diagnostics.Process process;
System.Diagnostics.ProcessStartInfo processStartInfo;
;
new InteropPermission(InteropKind::ClrInterop).assert();
process = new System.Diagnostics.Process();
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.set_FileName("C:\\temp\\test.bat");
processStartInfo.set_Arguments("Value1 Value2 Value3");
process.set_StartInfo(processStartInfo);
process.Start();
process.WaitForExit();
info("Finished");
}
Martin F
-
There is one interesing feature available in help file. You could link AX Form directly from help file. There is an example in standard AX 2009 installation.
- Open form Accounts receivable / Setup / Customer groups.
- Press F1
- Open file will be opened as on following picture
- There are a links in text as Customers or Term of payments.
- When you click on those links then coresponding AX Form will be opened directly.
How to achieve same function
With creating help file it will be necesary use a Help Kit for Microsoft Dynamics AX. Next tool which I will recommand you is a HTML Help Workshop and Documentation. For linking AX Form into code there is a special function located in script_main.js file located in folder local of help kit. Syntax of this function is following:
function AxMenuItemExecute(MIType, MenuItem)
{
try
{
var intMenuItemType;
switch (MIType)
{
case "Display":
intMenuItemType=0;
break;
case "Output":
intMenuItemType=1;
break;
case "Report":
intMenuItemType=2;
break;
default:
return; // Take no action.
break;
}
AxLabel.RunMenuItem(intMenuItemType, MenuItem);
}
catch (e) {
//window.alert("Failed to execute menu item.");
}
}
Using of this function is quite simple, there is an example of opening Term of payments.
<a onclick="AxMenuItemExecute('Display','paymterm')">Terms of payment</a>
To be able call this function successfull you have to add a reference to AxLabel object in each html page in your help file.
<OBJECT ID="AxLabel" CLASSID="CLSID:F5DD8727-673F-4523-869A-35AAA05AE782"></OBJECT>
Karel F
-
You may face a blocking issue on SQL Server each time you do any change in AOT. And you’re using database log. This is the problem. While using database log an insert trigger on SysDatabaseLog table is always dropped and recreated what is causing blocking issues on SysDatabaseLog table. There are 2 options how to solve this issue:
1. Do not use database log
2. Modify createDateTimeTrigMSSQLOnTable method in SysSQLinitDBTriggers class as follows:
...
if (resultSet.next() && (resultSet.getString(1) == '1'))
{
if (tableName == 'SYSDATABASELOG')
{
return;
}
sqls = 'DROP TRIGGER ' + dbSchema + "." + triggerName;
ssep2 = new SqlStatementExecutePermission ( sqls );
ssep2.assert();
statement.executeUpdate(sqls);
CodeAccessPermission::revertAssert();
}
…
Martin F
-
In batch job is not posible to call WinAPI functions WINAPI::FindFirstFile(..) and WINAPI::FindNextFile(...). This is limited only for code running on client. Sometimes is necesary have similar function for code running on server (or in batches). There is a code sample which is using .NET Framework.
static void Job1(Args _args)
{
FilePath sFilePath;
System.IO.DirectoryInfo di;
System.IO.FileInfo[] fis;
System.IO.FileInfo fi;
int i;
int l;
;
sFilePath;= "C:\\temp\\test\\";
di = new System.IO.DirectoryInfo(sFilePath;);
fis = di.GetFiles();
l = fis.get_Length();
for (i = 0; i < l; i++)
{
fi = fis.GetValue(i);
info(fi.get_FullName());
}
}
Karel F