Tip #60 | Suppress Warnings in Visual Studio Code

One of the most anoying things about writing AL code in Visual Studio Code is getting warnings that you cannot fix. Simply impossible.

My “favorite” warning is this one

For almost a decade it’s been possible to sort on flowfields from code and in reports and in most cases it works fine. On larger datasets it might require a covering index for performance.

This warning is a joke because it suggests to add a flowfield to the key’s. Even if it were a normal field; in extensions you cannot influence keys in Base Application anyway.

It’s recommended to fix this per project and to do this you need to add a settings.json file to your .vscode folder like this:

The content of this file should be something like this:

{
    "name": "ForNAV",
    "description": "ForNAV Rules",
    "generalAction": "Hidden",
    "rules": [
        {
            "id": "AL0432",
            "action": "Hidden",
            "justification": "Marked for removal, be careful with this rule…"
        },
        {
            "id": "AL0254",
            "action": "Hidden",
            "justification": "Not possible to solve"
        },

Tip #59 | Multiple Start Configurations in Visual Studio Code

When developing extensions for Business Central you have a wide array of publishing options to choose from.

My most used options when working on the ForNAV Customizable Report Pack are our Sandbox and Docker.

Testing is best on the Sanxbox for two reasons. First because all the Azure Active Directory stuff actually returns something which is useful for licensing scenario’s. Second because you can easily share the result with the team since everyone is on the same Sandbox.

Docker is useful when you don’t want to test on current but on an older or vNext instance.

Lastly it’s also possible to install Business Central on your own infrastructure altough this is a dying species.

In your Visual Studio Code project you can specify how you want to publish in the launch.json file but did you also know you can setup miltiple configurations and then choose one at the time of publishing.

This is how it could look:

{
     "version": "0.2.0",
     "configurations": [
         {
             "type": "al",
             "request": "launch",
             "name": "Docker",
             "authentication": "UserPassword",
             "startupObjectType": "Page",
             "breakOnError": true,
             "launchBrowser": true,
             "server": "http://bcsandbox",
             "serverInstance": "NAV",
             "enableLongRunningSqlStatements": true,
             "enableSqlInformationDebugger": true,
             "schemaUpdateMode": "Synchronize"
    },
    {
        "type": "al",
        "request": "launch",
        "name": "Microsoft cloud sandbox",
        "startupObjectId": 6188475,
        "startupObjectType": "Page",
        "breakOnError": true,
        "launchBrowser": true,
        "enableLongRunningSqlStatements": true,
        "enableSqlInformationDebugger": true,
        "schemaUpdateMode": "Synchronize"
    }
] 
}

Now if you publish your code Visual Studio Code will ask for the correct configuration.

NOTE: Your credentials cache is shared accross these configurations. You will need to clear the credentials cache if you switch.

TIP: You can also use this to create a seperate config for Syncronize and Recreate.

Tip #58 | Run Extension Objects

One of the quirks of working with extensions is that you cannot run an object from the object designer. This is true for V1 and V2.

With V2 you can start an object (page) after deploy but this only works once and only in the WebClient.

If you just quickly want to check our a page or codeunit in the Windows client you can write a codeunit against an object that does not exist.

An example is the TowersOfHanoi app that Microsoft ships as example. This does not have a page extension to execute itself.

Works all the time.

Want to learn more about extensions? Contact me today!

Why SQL Server 2016 Management Studio Understands Navision

I spend a lot of my time in SQL Server Management Studio. I rarely ever run tables anymore from Object Desingner and run most of my data conversions directly in T-SQL.

Why? Because it is so much faster, I can script things, save and restore scripts, share accross customers etc.

One of the pain points of working with SQL Server Queries has Always been the full companyname in front of the real table name. For this reason Intellisense was more or less useless for NAV databases.

This is fixed in SSMS 2016!

When you type

select * from Custom

SQL Server Management Studio will show this

sql-2016

How cool is that!

You can download SSMS 2016 for free here

 

 

Tip #56 | Fix Error : Sorting cannot be done based on the XX field(s)

Today I’ve spent some time in NAV2016 figuring out this error message:

Sorting

As you know in NAV2016 you can sort on each column even if there is no key and even if it’s a flowfield. So why am I getting this error?

In my case the Test field is a Flowfield of the type COUNT to another table. This should work fine, so why doesn’t it work here.

Reason is that the SQL Data Type is Integer instead of VarChar. A very old trick to make a SQL Database sort a Code field just like the Native database.

The SQL Data Type in the “Other” table does not match this SQL Type hence the sorting fails.

Since I could not find any info online on this message I thought it was worth sharng.

Sorting2

ALWAYS! Restart Service Tier after FOB Import!

Blogging about your own mistakes is always easiest. Reasoning is simple; if I make the mistake, chance is someone else makes it too.

Yesterday we had quite some panic at one of my large customers. After importing a fob file with some (small) changes some reports started to break that were not changed by the release.

Not all the users were suffering from this, only few, and after restarting the client, at first, the issue seems to be resolved.

However after a few hours we had the issue returning at users who had already restarted so we had some panic since it kind of goes against one of NAVs strong principles. Consistency. IF you have issues with NAV it is always relatively easy to reproduce.

Fortunately this was the case after some testing but debugging and restarting the client did not change the issue. It persisted.

What do you do in cases like this? Scream loud and wave your arms? No. Stay calm and look for differences. ;-).

After some thinking I realised that I had not restarted the service tier after importing the FOB. This “should not” be required since the new metadata is picked up automagically. However after restarting the service tier the issue was solved.

Since the issue was with a report, I emailed back and forth with Michael Nielsen who does first line support of the reporting tool we use, ForNAV. He confirmed quickly that importing a fob MAY cause inconsistency in your metadata and it is an issue that is very hard to troubleshoot or even reproduce with NAV.

So I’ve learned my lesson and will from now on always restart the service tier after importing fob files.

Tip #54 | PowerShell Merge – A clustered key can appear only once in a table

If you upgrade your database to NAV2016 using the PowerShell Merge commandlets and have a change to table 49 you will run into this issue.

Table 49 is the Invoice Posting Buffer table that NAV uses to create G/L entries for each unique combination of values in the Sales and Purchase documents. With the NAV2016 release Microsoft have added the Deferral Code field to this table and the primary key.
Continue reading “Tip #54 | PowerShell Merge – A clustered key can appear only once in a table”

Tip #53 – Locks, Blocks, Deadlocks and Timeouts | What are they

Recently I’ve been asked to do a code review of a vertical solution. Since these are always interesting projects I cleared my schedule and planned an interview to see what it was about. I’m curious by nature.

During the interview I was told that some of their customers were complaining about deadlocks. This was going on for a while now and they did their best to look at the problem and even created a chart with deadlocks per day.

This was honestly not that much so I figured something else must be wrong. After the intake we spent some time looking at one customers system and I started up some measurements in SQL Server Profiler. Nothing fancy, just some lock events.

2015-09-15_08-06-54

This showed that not deadlocks, but locktimeouts are causing the problem. From a user perspective they almost look the same.

Here is the deadlock message:

deadlock

And the locked message:

Lock

But the source of the problem can be entirely different.

Simulate a (b)lock timeout

This is realatively easy. Simply create one codeunit that reads a customer record and hold the transaction with a confirm. (Never do this in real life kids)

Lock Code

Now simply run this codeunit twice and the timeout message will appear.

Simulate a deadlock

This is a little harder. We need two codeunits this time.

deadlock code

In this scenario we read two different customer records with a confirm in between.

Start both codeunits and then quickly press the confirm message. If you do this within the locktimeout window (default 10 seconds) you will get a deadlock.

Locktable

This last example also proves the myth about locktable busted. This is probably the most ambiguous command in C/AL language. It does not what it implies. It does NOT lock the table, but only locks the specific rows you read in the database.

Microsoft, can you please rename this to something that makes more sense?

Tools

You can also measure blocks and deadlocks using the tools Jorg Stryk provides for free. http://dynamicsuser.net/blogs/stryk/archive/2014/10/10/directions-emea-2014-troubleshooting-nav-2013-r2.aspx

Tip #52 – Run MODAL pages after INSERT

One of the things I spend a lot of time on during my workshop is design for performance and using temporary tables. There are so many great things you can do here.

Let’s look at this code:

Buffer 1

Typically after an insert you would expect this error when trying a RUNMODAL

Buffer 2

But, not in this case. Here we have this:

Buffer 3

The reason why this works is the use of a temporary table. The record is not actually inserted into the SQL Server database.

Buffer 4

This is very useful for example when running a wizard. This allows you to roll back the transaction very easily when the wizard was cancelled.

Do you want to lean more?

During my workshop I spend a lot of time on these typical things in NAV that are poorly documented but very powerful.

The next workshop is in Copenhagen, close to the heart of NAV developement.

Register here. (QBS Partners can use vouchers)