wtorek, 20 grudnia 2011

Jaka data jest użyta przy przeliczaniu magazynu?

Wybór daty w AX 2009 uzależniony jest od parametrów.
Najpierw odwołania do transakcji biorących udział w przeliczaniu kopiowane są do tabeli tymczasowej, gdzie pole z datą brane jest z poniższego kawałka kodu:

wtorek, 29 listopada 2011

Generowanie klas AxBC

Skrypt do generowania klas AxBC.
Skrypt generuje klasy AxBC dla tabeli InventItemBarcode. Wynikiem jego pracy są dwie klasy AxInventItemBarcode oraz AxInventDim_InventItemBarcode.
static void SBR_GenerateAxBC(Args _args)
{ 
    AxGenerateAxBCClass axGenerateAxBCClass;
    ;
    axGenerateAxBCClass = AxGenerateAxBCClass::newTableId(tablenum(InventItemBarcode));
    axGenerateAxBCClass.parmInboundAxBCClass(true);
    axGenerateAxBCClass.generateInventDim();
    axGenerateAxBCClass.run();
}
Nowe klasy musimy jeszcze ręcznie przerobić (usunąć zbędne metody i odblokować linię w metodzie new()).

poniedziałek, 28 listopada 2011

Automatyczne tworzenie klas

Czasami trzeba stworzyć klasę z dużą ilościa zmiennych, aby nie tracić czasu polecam szybkiego joba. Stworzy on nową klasę z podanymi parametrami.
static void SBR_CLASS_CREATOR(Args _args)
{
    ClassBuild  classBuild;
    
#localMacro.addParam
    classBuild.addSourceToMethod("classDeclaration", "\n" + %1 + " " + %2 + ";");
    classBuild.addMethod("parm" + strupr(substr(%2, 1, 1)) + substr(%2, 2, 999999),
                "public "+ %1 +" parm" + strupr(substr(%2, 1, 1)) + substr(%2, 2, 999999) +"("+ %1 +" _"+ %2 +" = "+ %2 +")\n"+
                "{\n"+
                ";\n"+
                "    "+ %2 +" = _"+ %2 +";\n"+
                "    return "+ %2 +";\n"+
                "}")
#endMacro

    ;

    classBuild = new ClassBuild("Nazwa_klasy", false);
    // Pierwsza zmienna w makro - nazwa typu
    // Druga zmienna w makro - nazwa zmiennej
    #addParam("ItemId", "itemId");
    #addParam("ItemId", "altItemId");
    #addParam("SalesID", "salesId");

    pause;

}

środa, 23 listopada 2011

UTCDateTime

Pobieranie daty i czasu uwzględniając strefę czasową użytkownika
UTCDateTime dateTime;
;
dateTime = DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::utcNow(), DateTimeUtil::getClientMachineTimeZone());

poniedziałek, 21 listopada 2011

Statystyki

Wyszukiwanie dat aktualizacji statystyk dla konkretnej tabeli
SELECT 
 T.object_id, 
 T.name, 
 S.name AS stats_name, 
 S.auto_created, 
 STATS_DATE(T.object_id, S.stats_id) AS [stats_date] 
FROM sys.tables T join sys.stats S  ON T.object_id = S.object_id 
WHERE T.type = 'U' AND T.name = 'INVENTTRANS'
ORDER BY [stats_date] DESC
To samo dla wersji SQL 2000
SELECT 
 o.name AS [table_name], 
 i.name AS [stats_name], 
 STATS_DATE(o.id, i.indid) AS [stats_date] 
FROM dbo.sysobjects o join dbo.sysindexes i ON o.id = i.id
WHERE o.name = 'INVENTTRANS'
ORDER BY [stats_date] DESC
Szczegółowe informacje o statystyce
DBCC SHOW_STATISTICS(INVENTTRANS, '_WA_Sys_00000041_5793BE78')
Aktualizacja statystyk
UPDATE STATISTICS table_or_indexed_view_name 
    [ 
        { 
            { index_or_statistics__name }
          | ( { index_or_statistics_name } [ ,...n ] ) 
                }
    ] 
    [    WITH 
        [ 
            [ FULLSCAN ] 
            | SAMPLE number { PERCENT | ROWS } ] 
            | RESAMPLE 
            |  [ ,...n ]
        ] 
        [ [ , ] [ ALL | COLUMNS | INDEX ] 
        [ [ , ] NORECOMPUTE ] 
    ] ;

piątek, 18 listopada 2011

C# Zapis do pliku XML

Przykład generowania pliku XML.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace NL_XMLExample
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlTextWriter XmlWriter = new XmlTextWriter("C:\\TEMP\\out.xml", null);
            
            XmlWriter.WriteStartDocument();
            
            XmlWriter.WriteComment("This is the comments.");

            XmlWriter.WriteStartElement("BOOKS");
            
            XmlWriter.WriteAttributeString("LANGUAGE", "Any");

            XmlWriter.WriteStartElement("BOOK");
            XmlWriter.WriteElementString("TITLE", "this is the title.");
            XmlWriter.WriteElementString("AUTHOR", "I am the author.");
            XmlWriter.WriteElementString("PUBLISHER", "who is the publisher.");
            XmlWriter.WriteEndElement();

            XmlWriter.WriteStartElement("BOOK");
            XmlWriter.WriteElementString("TITLE", "this is the title 2.");
            XmlWriter.WriteElementString("AUTHOR", "I am the author 2.");
            XmlWriter.WriteElementString("PUBLISHER", "who is the publisher 2.");
            XmlWriter.WriteEndElement();

            XmlWriter.WriteEndElement();
            
            XmlWriter.WriteEndDocument();
            XmlWriter.Close();            
        }
    }
}
Wynik.



    
        this is the title.
        I am the author.
        who is the publisher.
    
    
        this is the title 2.
        I am the author 2.
        who is the publisher 2.
    


środa, 2 listopada 2011

Stronicowanie w AX 2009

static void B2B_Paging_New(Args _args)
{
    Query       query;
    QueryRun    queryRun;
    InventTrans inventTrans;
    ;
    query = new Query();
    query.addDataSource(tableNum(InventTrans));

    // do stronicowanie wymagane jest co najmniej jedno pole sortowania
    query.dataSourceTable(tableNum(InventTrans)).addSortField( fieldNum(InventTrans, Recid), SortOrder::Descending);    

    queryRun = new QueryRun(query);

    // włącz stronicowanie
    queryRun.enablePositionPaging(true);

    // pobierz 10 rekordów zaczynając od rekordu 80000 
    queryRun.addPageRange(80000, 10);
    
    while(queryRun.next())
    {
        inventTrans = queryRun.get(tableNum(InventTrans));
        print inventTrans.RecId;
    }
    pause;
}

wtorek, 25 października 2011

ATTACH_FORCE_REBUILD_LOG

W wielu systemach bazodanowych plik loga (LDF) znajduje sie na oddzielnych dyskach niż pliki danych (MDF, NDF).
Co zrobić jeśli w przypadku awarii utracimy plik LDF (np.: awaria sprzetowa dysków)? Odpowiedź jest prosta - przywracamy backup.

Co w przypadku gdy jednak chcemy odzyskać dane z pliku MDF?
W sieci można znaleźć wiele dziwnych opisów odzyskiwania pliku MDF po stracie LDF, większość z nich pochodzi jeszcze z czasów SQL Server 2000.

Od wersji SQL Server 2005 istnieje nieudokumentowany parametr do polecenia 'CREATE DATABASE' umożliwiający podpięcie samej bazy danych bez pliku LDF.

Przykład:
Tworzymy nową bazę danych :
CREATE DATABASE [Demo] ON  PRIMARY 
( NAME = N'Demo', FILENAME = N'C:\Temp\Demo.mdf')
 LOG ON 
( NAME = N'Demo_log', FILENAME = N'C:\Temp\Demo_log.ldf')
GO

USE [Demo]
GO

CREATE TABLE Items(Id INT IDENTITY(1,1) PRIMARY KEY, Name VARCHAR(20), Price MONEY)
GO

INSERT INTO Items VALUES ('CAR', 100000);
INSERT INTO Items VALUES ('PARTS', 2000);
GO
Rozpoczynamy transakcję modyfikującą dane:
BEGIN TRAN;
UPDATE Items SET Price = 0 WHERE Name = 'PARTS'
GO

CHECKPOINT;
GO
Na innej konsoli zatrzymujemy serwer bazodanowy:
SHUTDOWN WITH NOWAIT;
GO
Po zatrzymaniu serwera SQL usuwamy plik LDF (w naszym przypadku 'C:\Temp\Demo_log.ldf') i startujemy serwer SQL ponownie.
Po zalogowaniu się do serwera sprawdzamy status bazy danych:
SELECT DATABASEPROPERTYEX ('Demo', 'STATUS') AS 'Status';
Jest SUSPECT, czyli zgodnie z oczekiwaniami. Teraz odłączamy baze danych.
ALTER DATABASE Demo SET OFFLINE
GO
EXEC sp_detach_db 'Demo';
GO
i próbujemy podpiąć ją standardowymi komendami:
CREATE DATABASE DemoFix ON
   (NAME = DemoSuspect, FILENAME = N'C:\Temp\Demo.mdf')
FOR ATTACH_REBUILD_LOG;
GO
File activation failure. The physical file name "C:\Temp\Demo_log.ldf" may be incorrect. The log cannot be rebuilt because there were open transactions/users when the database was shutdown, no checkpoint occurred to the database, or the database was read-only. This error could occur if the transaction log file was manually deleted or lost due to a hardware or environment failure. 
Msg 1813, Level 16, State 2, Line 1 Could not open new database 'DemoFix'. CREATE DATABASE is aborted.

Spróbujmy zatem naszego nowego polecenia:
CREATE DATABASE DemoFix ON
   (NAME = DemoSuspect, FILENAME = N'C:\Temp\Demo.mdf')
FOR ATTACH_FORCE_REBUILD_LOG;
GO
File activation failure. The physical file name "C:\Temp\Demo_log.ldf" may be incorrect.
New log file 'C:\Temp\DemoFix_log.LDF' was created.


Baza działa! Ale niestety nie jest tak pięknie. Stworzona baza danych nie jest spójna. Zobaczmy co znajduje się w naszej tabeli w nowej bazie:
SELECT * FROM [DemoFix].[dbo].[Items]

Jak widać w tabeli zapisane są modyfikacje transakcji która się nie zakończyła.

poniedziałek, 24 października 2011

Start

Test formatowania kodu SQL:
-- QUERY1
SELECT  
 H.SalesOrderNumber, H.AccountNumber, S.Name AS [CustomerName], P.ProductID, P.Name, D.OrderQty, D.LineTotal
 FROM Sales.SalesOrderDetail D
 INNER JOIN Production.Product P ON P.ProductID = D.ProductID
 INNER JOIN Sales.SalesOrderHeader H ON H.SalesOrderID = D.SalesOrderID
 INNER JOIN Sales.Customer C ON C.CustomerID = H.CustomerID
 INNER JOIN Sales.Store S ON S.BusinessEntityID = C.StoreID
WHERE D.SalesOrderID = 43933