Während meines Vortrages habe ich ein SQL-Statement gezeigt, welches mit dem SQL-Profiler während der Laufzeit einer Query aufgezeichnet wurde.

Hierbei handelt es sich um eine Query, welche das selbe Ergebnis liefert wie der TOP-10-Debitoren-Report. Die Query benötigt gerade in großen Datenbank merklich weniger Zeit.

Hier noch einmal das SQL-Statement zum nachlesen:

SELECT TOP (10) ISNULL(“Customer”.”No_”,@0) AS “No”,ISNULL(“Customer”.”Name”,@1) AS “Name”,ISNULL(SUM(“SUB$Customer$Sales (LCY)“.”Sales (LCY)$Cust_ Ledger Entry$SUM$Sales (LCY)”),@3) AS “Sum_Sales_LCY”,ISNULL(SUM(“SUB$Customer$Balance (LCY)“.”Balance (LCY)$Detailed Cust_ Ledg_ Entry$SUM$Amount (LCY)”),@5) AS “Sum_Balance_LCY” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Customer” AS “Customer” WITH(READUNCOMMITTED)

OUTER APPLY (SELECT TOP (1) ISNULL(SUM(“Sales (LCY)$Cust_ Ledger Entry”.”Sales (LCY)”),@2) AS “Sales (LCY)$Cust_ Ledger Entry$SUM$Sales (LCY)” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Cust_ Ledger Entry” AS “Sales (LCY)$Cust_ Ledger Entry” WITH(READUNCOMMITTED)  WHERE (“Sales (LCY)$Cust_ Ledger Entry”.”Customer No_”=”Customer”.”No_”)) AS “SUB$Customer$Sales (LCY)

OUTER APPLY (SELECT TOP (1) ISNULL(SUM(“Balance (LCY)$Detailed Cust_ Ledg_ Entry”.”Amount (LCY)”),@4) AS “Balance (LCY)$Detailed Cust_ Ledg_ Entry$SUM$Amount (LCY)” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Detailed Cust_ Ledg_ Entry” AS “Balance (LCY)$Detailed Cust_ Ledg_ Entry” WITH(READUNCOMMITTED)  WHERE (“Balance (LCY)$Detailed Cust_ Ledg_ Entry”.”Customer No_”=”Customer”.”No_”)) AS “SUB$Customer$Balance (LCY)

ORDER BY “Sales_LCY” DESC,”No” ASC OPTION(OPTIMIZE FOR UNKNOWN, FAST 50, FORCE ORDER, LOOP JOIN)

Dies ist auch ein schönes Beispiel wie die Query im Hintergrund mit verschachtelten Abfragen, der TOP-Klausel und den SQL eigenen Funktionen wie SUM arbeitet.

During my airlift presentation I have shown a SQL-Statement which was captured using sql profiler during runtime of a query-object.

This query brings the same results as TOP10-Customer-Report, but in shorter time.

Here is what the statement behind the query looks like.

SELECT TOP (10) ISNULL(“Customer”.”No_”,@0) AS “No”,ISNULL(“Customer”.”Name”,@1) AS “Name”,ISNULL(SUM(“SUB$Customer$Sales (LCY)”.”Sales (LCY)$Cust_ Ledger Entry$SUM$Sales (LCY)”),@3) AS “Sum_Sales_LCY”,ISNULL(SUM(“SUB$Customer$Balance (LCY)”.”Balance (LCY)$Detailed Cust_ Ledg_ Entry$SUM$Amount (LCY)”),@5) AS “Sum_Balance_LCY” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Customer” AS “Customer” WITH(READUNCOMMITTED)

OUTER APPLY (SELECT TOP (1) ISNULL(SUM(“Sales (LCY)$Cust_ Ledger Entry”.”Sales (LCY)”),@2) AS “Sales (LCY)$Cust_ Ledger Entry$SUM$Sales (LCY)” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Cust_ Ledger Entry” AS “Sales (LCY)$Cust_ Ledger Entry” WITH(READUNCOMMITTED)  WHERE (“Sales (LCY)$Cust_ Ledger Entry”.”Customer No_”=”Customer”.”No_”)) AS “SUB$Customer$Sales (LCY)

OUTER APPLY (SELECT TOP (1) ISNULL(SUM(“Balance (LCY)$Detailed Cust_ Ledg_ Entry”.”Amount (LCY)”),@4) AS “Balance (LCY)$Detailed Cust_ Ledg_ Entry$SUM$Amount (LCY)” FROM “Demo Database NAV (7-0)”.”dbo”.”CRONUS AG$Detailed Cust_ Ledg_ Entry” AS “Balance (LCY)$Detailed Cust_ Ledg_ Entry” WITH(READUNCOMMITTED)  WHERE (“Balance (LCY)$Detailed Cust_ Ledg_ Entry”.”Customer No_”=”Customer”.”No_”)) AS “SUB$Customer$Balance (LCY)

ORDER BY “Sales_LCY” DESC,”No” ASC OPTION(OPTIMIZE FOR UNKNOWN, FAST 50, FORCE ORDER, LOOP JOIN)

This example shows how the query-object increases performance by the usage of TOP, nested statements and SUM.

Habt ihr schon einmal die neuen Möglichkeiten mit OData ausprobiert die euch Microsoft Dynamics NAV 2013 bietet?

Hier einmal ein kurzer Überblick über die Zugriffsmöglichkeiten auf OData-Webservices.

Alle hier genannten Beispiele funktionieren mit der Standardinstallation von Cronus und dem veröffentlichten Webservice Customer mit dem Typ Seite und der ID 22.

 

Zeige alle OData-feeds:

http://localhost:7048/DynamicsNAV70/odata

Zeige Metadaten:

http://localhost:7048/DynamicsNAV70/odata/$metadata

Gib alle Debitoren aus:

http://localhost:7048/DynamicsNAV70/odata/Customer

Gib den Debitoren mit dem Primärschlüssel 10000 aus (Primärschlüssel verwenden):

http://localhost:7048/DynamicsNAV70/odata/Customer(‘10000’)

Gib alle Debitoren mit dem Lagerort BLAU aus (Verwendung von Feldfiltern):

http://localhost:7048/DynamicsNAV70/odata/Customer?$filter=Location_Code eq ‘BLAU’

Gib Name, Lagerortcode und Kreditlimit(MW) aus (Abruf einzelner Felder):

http://localhost:7048/DynamicsNAV70/odata/Customer?$select=Name, Location_Code, Credit_Limit_LCY

Gib Name, Lagerortcode und Kreditlimit (MW) für alle Debitoren aus der Lagerortcode BLAU ist (einzelne Felder kombiniert mit Filtern):

http://localhost:7048/DynamicsNAV70/odata/Customer?$filter=Location_Code eq ‘BLAU’ &$select=Name, Location_Code, Credit_Limit_LCY

Did you already try out the new possibilities of OData coming with Microsoft Dynamics NAV 2013?

Here is a quick summary of what you can do when accessing OData webservice.

All examples can be done with default installation of Cronus and publishing Page 22 as a webservice with the name Customer.

 

Show all OData-feeds:

http://localhost:7048/DynamicsNAV70/odata

Show Metadata:

http://localhost:7048/DynamicsNAV70/odata/$metadata

Show all customers:

http://localhost:7048/DynamicsNAV70/odata/Customer

Show customer with the primary key 10000 (using key):

http://localhost:7048/DynamicsNAV70/odata/Customer(‘10000’)

Show all customers with Location Code BLUE (using field-filter):

http://localhost:7048/DynamicsNAV70/odata/Customer?$filter=Location_Code eq ‘BLUE’

Show Name, Location Code and Credit Limit (LCY) from customers (selecting a couple of fields only):

http://localhost:7048/DynamicsNAV70/odata/Customer?$select=Name, Location_Code, Credit_Limit_LCY

Show Name, Location Cod and Credit Limit (LCY) for customers with Location Code BLUE (selection and filter):

http://localhost:7048/DynamicsNAV70/odata/Customer?$filter=Location_Code eq ‘BLUE’ &$select=Name, Location_Code, Credit_Limit_LCY

Beim arbeiten mit Microsoft Dynamics NAV kann es passieren, dass die Metadaten eines Objektes korrupt sind.

Das ist an und für sich kein Problem, da die Metadaten immer dann neu erzeugt werden, wenn ich das Objekt über den Object Designer kompiliere. Aber wie sieht das bei den versteckten Systemtabellen aus?

Oder was fast noch schlimmer ist: Was mache ich, wenn ich versehentlich alle Metadaten gelöscht habe?

Dieses Problem lässt dich nur auf einem Weg korrekt lösen.

Erst öffnest du den “Alter Database”-Dialog und setzt die Datenbank in den single user Zustand.

Anschliessend wird das Kennzeichen Enable for Microsoft Dynamics NAV Server deaktiviert..

Wenn das alles durch ist setzt du den Haken wieder und kannst zuschauen wir der Client die Objekte (inklusive der Systemtabellen) kopmiliert. Ist dieser damit fertig muss die Datenbank nur noch für Benutzer wieder frei gegeben werden. (Single user wieder deaktivieren)

When working with Microsoft Dynamics NAV it can happen that you receive a message about metadata-problems while trying to open the RTC.

This is no problem, you simply have to compile the object and everything is fine again. In some early builds there were cases when you had to delete the metadata of this objects before compiling it again.

But what to do if the object is a hidden systemtable? You cannot choose it in Object Designer for compiling.

Or even worse, you accidentally deleted all metadata.

To fix this problem you should set the database to Single user and disable the database for Microsoft Dynamics NAV Server.

This can be done with alter database. Afterwards you re-enable for Microsoft Dynamics NAV and remove the single user flag again.

This causes the Client to recompile most of the objects, including system-tables.