Read Dynamics NAV Table Metadata with SQL

前端 未结 3 550
南方客
南方客 2020-12-10 08:26

I would like to be able to read the Dynamics NAV 2013 Table Metadata directly from the SQL Server database without requiring the NAV Development Environment.

I can v

相关标签:
3条回答
  • 2020-12-10 08:45

    It is possible to extract metadata from this table through Nav and as I can see it is stored as plain text but in binary field. It can be saved to file using simple MemoryStream (in Nav it is called OutSteram). So for table number 3 I get following XML:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <MetaTable xmlns="urn:schemas-microsoft-com:dynamics:NAV:MetaObjects" ID="3" CaptionML="ENU=Payment Terms;RUS=Условия платежа" DataPerCompany="1" Name="Payment Terms" LookupFormID="4" DataCaptionFields="1,5">
        <Fields>
            <Field ID="1" Datatype="Code" DataLength="10" Enabled="1" FieldClass="Normal" Name="Code" CaptionML="ENU=Code;RUS=Код" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" NotBlank="1" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
            <Field ID="2" Datatype="DateFormula" Enabled="1" FieldClass="Normal" Name="Due Date Calculation" CaptionML="ENU=Due Date Calculation;RUS=Расчет срока оплаты" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" NotBlank="0" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
            <Field ID="3" Datatype="DateFormula" Enabled="1" FieldClass="Normal" Name="Discount Date Calculation" CaptionML="ENU=Discount Date Calculation;RUS=Расчет даты скидки" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" NotBlank="0" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
            <Field ID="4" Datatype="Decimal" Enabled="1" FieldClass="Normal" Name="Discount %" CaptionML="ENU=Discount %;RUS=Скидка (%)" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" MinValue="0" MaxValue="100" NotBlank="0" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
            <Field ID="5" Datatype="Text" DataLength="50" Enabled="1" FieldClass="Normal" Name="Description" CaptionML="ENU=Description;RUS=Описание" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" NotBlank="0" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
            <Field ID="6" Datatype="Boolean" Enabled="1" FieldClass="Normal" Name="Calc. Pmt. Disc. on Cr. Memos" CaptionML="ENU=Calc. Pmt. Disc. on Cr. Memos;RUS=Расчет скидки оплаты по кредит-нотам" BlankNumbers="DontBlank" BlankZero="0" SignDisplacement="0" Editable="1" NotBlank="0" Numeric="0" DateFormula="0" ClosingDates="0" Title="0" AutoIncrement="0" ValidateTableRelation="1" TestTableRelation="1" ExtendedDatatype="None"/>
        </Fields>
        <Keys>
            <Key Enabled="1" Key="Field1" MaintainSQLIndex="1" MaintainSIFTIndex="1" Clustered="1"/>
        </Keys>
        <FieldGroups>
            <FieldGroup GroupID="1" GroupName="DropDown" GroupFields="Field1,Field5,Field2"/>
        </FieldGroups>
    </MetaTable>
    

    Suppose this is what you want.

    Code writing it to file in Nav will look like this:

    ObjectMetadata:Record(Object Metadata)
    Code:BigText
    File:File       
    CodeStream:InStream     
    FileStream:OutStream        
    
    ObjectMetadata.INIT;
    
    IF ObjectMetadata.GET(1,3) THEN
     BEGIN
      ObjectMetadata.CALCFIELDS(Metadata);
      File.CREATE('C:\temp\Code.txt');
      File.CREATEOUTSTREAM(FileStream);
    
      clear(codestream);
      ObjectMetadata."Metadata".CREATEINSTREAM(CodeStream);
      Code.READ(CodeStream);
      Code.WRITE(FileStream);
    
      file.close();
     END;
    

    Now you have options: try to do same thing in SQL/.Net (I'm not keen with it) or you can ask your Nav developer to make some kind of batch job that will periodically (or on demand) process all tables' matadata and save it to external table/file/whatever which you can access from SQL.

    0 讨论(0)
  • 2020-12-10 08:58

    I was able to get an answer for the format of these Metadata binary fields from the author of the deV.ch - man vs. code, Dynamics NAV & C# .NET blog. Based on the reverse engineering by devch, we determined that the first four bytes (32 bits) of these fields are used by NAV to store a "magic number" that determines the custom NAV Blob type.

    In the case of these metadata fields, the NAV Compressed Blob-Type magic number is 0x02457d5b (hex). In order to use the standard .Net DeflateStream to Decompress, just throw away those first four magic-number bytes and then process the rest of the stream with DeflateStream as usual.

    I was able to successfully test this process with .Net, now I plan to test with Python or some other non-Microsoft deflate tools to see if the deflate implementation follows the industry standard. Thanks again to devch for the article that led to this solution: Accessing Compressed Blobs from outside NAV (NAV2013) (Revisited).

    Update: tested with Python zlib and it works! Standards-compliant Deflate algorithm is used once the custom NAV Blob-type magic number is removed. Here's some sample code (Python):

    # Example Using Python 3.x
    import zlib, sys, struct
    
    # NAV custom Blob-Type identifier (first 4 bytes)
    magic = struct.unpack('>I',sys.stdin.buffer.read(4))[0]
    print('magic number = %#010x' % magic, file=sys.stderr)
    # Remaining binary data is standard DEFLATE without header
    input = sys.stdin.buffer.read()
    output = zlib.decompress(input,-15)
    sys.stdout.buffer.write(output)
    

    Use something like the following to test:

    python -u test.py < Input_Meta.blob > Output_Meta.txt
    

    Of course the .Net DeflateStream works after removing the first four bytes as well. This example is just to show that you're not limited to using .Net languages.

    0 讨论(0)
  • 2020-12-10 09:12

    Why not use webservices and get the data you need without having to do anything fancy?

    Users can then use PowerPivot for Excel and create their own reports.

    You could also use the Excel Add-In for NAV and just export data to excel directly from NAV and then refresh from within Excel.

    0 讨论(0)
提交回复
热议问题