我希望能够在没有Dynamics NAV 2013 Table Metadata的情况下直接从SQL Server数据库中读取requiring the NAV Development Environment。
我可以使用如下所示的查询查看二进制SQL“image”BLOB列(根据WHERE子句过滤):
SELECT
o.[Name],
m.[Object Type],
m.[Metadata], -- XML Metadata
m.[User Code], -- C# Metadata
m.[User AL Code] -- C/AL Metadata
FROM [Navision].[dbo].[Object Metadata] AS m
JOIN [Navision].[dbo].[Object] AS o
ON m.[Object ID] = o.[ID]
AND o.[Company Name] = 'YourCompanyName'
AND o.[Type] = 0 -- 0 is NAV Table Object Type
我可以使用.Net代码或带有SQL驱动程序的快速脚本将[元数据],[用户代码]和[用户AL代码]中的二进制数据保存到文件中。我尝试使用7-zip解压缩,使用十六进制编辑器查看,并使用Cygwin“file”命令检测这些BLOB文件类型。
不幸的是,我无法弄清楚如何将二进制数据解码或解压缩成可读或可用的格式。直到我可以直接使用这些字段中的数据,我必须open NAV Dev Environment and use the Object Designer to view the comma-separated OptionString properties为基于零的查找列表下拉菜单(列表中的每个项目作为整数存储在后端数据库中 - 0表示第一个项目,1秒,等等)。 SQL查找表中不存在字符串值,但NAV确实将它们放在表元数据blob中。
这是我完全支持我作为DBA的NAV用户而不需要NAV开发人员为我查找这些数字到名称的NAV自定义字段映射的缺失链接。然后,我可以查找这些列表值,并根据需要创建匹配的SQL CASE语句或自定义查找表。
有了这篇文章,我应该能够创建高级SQL视图,查询,报告和工具,而无需访问Dynamics NAV前端用户或开发人员工具。
如果您了解用于这些NAV对象元数据blob属性的二进制数据格式,请告诉我。关于如何转换为可读或可用格式的任何建议都会有所帮助。
答案 0 :(得分:3)
可以通过Nav从此表中提取metadata
,我可以看到它以纯文本形式存储在二进制字段中。它可以使用简单的MemoryStream
保存到文件中(在Nav中称为OutSteram
)。因此,对于表3,我得到以下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>
假设这是你想要的。
将代码写入Nav中的文件的代码如下所示:
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;
现在你有了选择:尝试在SQL / .Net中做同样的事情(我不喜欢它)或者你可以让你的Nav开发人员做出某种定期(或按需)过程的批处理作业所有表的matadata并将其保存到外部表/文件/您可以从SQL访问的任何内容。
答案 1 :(得分:3)
我能够从deV.ch - man vs. code, Dynamics NAV & C# .NET blog的作者那里得到这些元数据二进制字段格式的答案。基于devch的逆向工程,我们确定NAV使用这些字段的前四个字节(32位)来存储确定自定义NAV Blob类型的“幻数”。
在这些元数据字段的情况下,NAV Compressed Blob-Type幻数为0x02457d5b(十六进制)。为了使用标准的.Net DeflateStream进行解压缩,只需丢弃前四个魔术数字字节,然后像往常一样使用DeflateStream处理剩余的流。
我能够使用.Net成功测试此过程,现在我计划使用Python或其他一些非Microsoft deflate工具进行测试,以查看deflate实现是否符合行业标准。再次感谢发布导致此解决方案的文章:Accessing Compressed Blobs from outside NAV (NAV2013) (Revisited)。
更新:使用Python zlib测试,它的工作原理!一旦删除了自定义NAV Blob类型幻数,就会使用符合标准的Deflate算法。这是一些示例代码(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)
使用以下内容进行测试:
python -u test.py < Input_Meta.blob > Output_Meta.txt
当然.Net DeflateStream也可以在删除前四个字节后工作。这个例子只是为了表明你不仅限于使用.Net语言。
答案 2 :(得分:1)
为什么不使用网络服务并获得所需的数据而不必做任何花哨的事情?
然后,用户可以使用PowerPivot for Excel并创建自己的报告。
您还可以使用Excel加载项进行NAV,只需将数据直接从NAV导出到excel,然后从Excel中刷新。