[AX]AX2012 AIF(二):文档服务编程模型
一個完整的文檔服務(wù)包含很多對象,以Customer服務(wù)為例,它包含以下對象:
- 查詢AxdCustomer:這個query的頂層表為CustTable,其下Datasource包含表DirParty,DirParty下的Datasource則再包含表DirPersonName、表DirOrganizationName、視圖DirPartyContactInfoView、視圖DirPartyPostalAddressView。這個Query定義了服務(wù)所用的所有相關(guān)數(shù)據(jù)的數(shù)據(jù)模型。
- 文檔服務(wù)類CustCustomerService:這是直接提供服務(wù)的類,它包含Create、Delete、find、findKeys、getKeys、getChangedKeys等對外服務(wù)的方法,這些方法使用特定的特性標(biāo)注,比如Create方法使用了[AifDocumentCreateAttribute, SysEntryPointAttribute(true)]標(biāo)注,AifDocumentCreateAttribute指出這個方法是文檔服務(wù)的創(chuàng)建方法,這個特性不是必須的,主要用途是在使用metadata服務(wù)時我們可以根據(jù)這個特性列舉出所有刪除記錄的服務(wù)操作;SysEntryPointAttribute特性指示是否進(jìn)行授權(quán)檢查,所有的服務(wù)操作必須指定這個特性,其參數(shù)true表示要對調(diào)用用戶檢查是否有權(quán)操作該方法涉及到的數(shù)據(jù)表,false則不執(zhí)行這個檢查。文檔服務(wù)類服務(wù)的具體操作都交由其繼承的基類AifDocumentService具體操作,比如read()方法內(nèi)部調(diào)用的是AifDocumentService.readList()方法。
- 數(shù)據(jù)對象類CustCustomer、CustCustomer_CustTable、CustCustomer_DirParty、CustCustomer_DirParty_DirPerson等:這些類描述了查詢AxdCustomer定義的數(shù)據(jù)模型,CustCustomer直接對應(yīng)Query AxdCustomer,它是數(shù)據(jù)對象類的最頂層,它依靠其他數(shù)據(jù)類CustCustomer_CustTable、CustCustomer_DirParty等。CustCustomer從AifDocument繼承,后者又從AfStronglyTypedDataContainer繼承,而AfStronglyTypedDataContainer又從AifXmlSerializable繼承,由它描述了XML消息定義的一個文檔,所以我們在read()服務(wù)操作方法中看到的返回值就是這個類的一個實(shí)例。其他的數(shù)據(jù)對象類都直接從AfStronglyTypedDataContainer繼承,所以數(shù)據(jù)對象類包括CustCustomer都實(shí)現(xiàn)一系列的existsXXX()方法,這些方法判斷某個字段是否存在,調(diào)用基類的exists()方法;一系列parmXXX()方法,獲取某個字段的值或者下層的數(shù)據(jù)對象實(shí)例;createXXX()方法,創(chuàng)建并返回其下層的數(shù)據(jù)對象類實(shí)例列表,比如CustCustomer.createCustTable()返回包含CustCustomer_CustTable類實(shí)例的列表。
- 文檔類AxdCustomer:文檔類的作用是封裝涉及到的多個表業(yè)務(wù)邏輯,這樣外部調(diào)用應(yīng)用不需要確切的知道如何操作底層數(shù)據(jù)庫表。Axd類實(shí)現(xiàn)AifServiceable接口,這里的AxdCustomer不是直接實(shí)現(xiàn)這個接口,而是從AxBase擴(kuò)展,后者實(shí)現(xiàn)AifServiceable接口。總體上來講Axd類實(shí)現(xiàn)到XML的序列化及反序列化,生成XSD數(shù)據(jù)Schema,控制內(nèi)部表的生命周期等,由它間接的操作下面要講到的AxXXX表類。Axd類包含的方法很多,更詳細(xì)的介紹可以參見http://msdn.microsoft.com/EN-US/library/aa862063.aspx,這里列舉幾個實(shí)現(xiàn)接口AifServiceable比較重要的方法:getName()返回文檔的名稱,這是XML文檔的根標(biāo)簽的名稱;getSchema()返回數(shù)據(jù)Schema XSD;getActionList()返回文檔支持的操作列表,比如AxdCustomer支持findList、read、readList等操作。
- 表類AxCustTable、AxDirPartyTable等:這組類以Ax<Table>方式命名,和文檔類協(xié)同工作,同樣封裝數(shù)據(jù)表業(yè)務(wù)邏輯,從AxInternalBase繼承,代表了AOT中的某個表。Ax<Table>類不是必須的,在使用AIF Document Wizard創(chuàng)建新的文檔服務(wù)時,勾選了“Generate AxBC Classes”才會創(chuàng)建這些類。如果使用Ax<Table>類,可以在文檔級別使用“Value mapping” form來映射數(shù)據(jù)表字段。Ax<Table>內(nèi)部使用類AxdBaseRead、AxdBaseCreate讀寫數(shù)據(jù)庫表,不使用Ax<Table>的情況則可以在Axd文檔類中使用AxCommon讀寫數(shù)據(jù)庫表。需要注意的如果在服務(wù)的Query中添加了一個新的表,相應(yīng)的Ax<Table>類不會自動生成,這時候可以使用“Update document service”工具的“Regenerate data object classes”和“Update AxBC classes”選項(xiàng)重新生成或者更新Ax<Table>類。Ax<Table>類和AOT中的表是一一對應(yīng)的,由它直接操作表數(shù)據(jù),具體功能包括生成表字段的默認(rèn)值、按照正確的順序設(shè)置表字段值、維護(hù)驗(yàn)證關(guān)聯(lián)表數(shù)據(jù)的完整性、字段值映射比如從供應(yīng)商料名映射到內(nèi)部料名、錯誤處理等,需要注意的是Ax<Table>不會驗(yàn)證是誰在操作數(shù)據(jù)表,用戶驗(yàn)證要放到前面提到的服務(wù)類。
看完相關(guān)的類和對象,在開始后續(xù)的問題前,我們先來看看Schema XSD是如何生成的。數(shù)據(jù)對象類繼承自AifDocument(頂級對象),也可能是AfStronglyTypedDataContainer,AfStronglyTypedDataContainer有一個方法叫做getSchema()返回Schema XSD;而AifDocument是繼承自AfStronglyTypedDataContainer,它重載了getSchema()方法,它會創(chuàng)建對應(yīng)Axd類的實(shí)例,調(diào)用前面提及的Axd類的getSchema()返回Schema XSD。實(shí)際上無論是AifDocument.getSchema()還是AfStronglyTypedDataContainer.getSchema(),它們最終都使用AxdBaseGenerateXSD.generate()生成Schema XSD。這里不深入討論是如何生成XSD的,需要知道的是以上方法會枚舉文檔定義的Query,從Query中查找Datasource字段生成相應(yīng)的XML標(biāo)記,文檔Query必須只有一個根Datasource,隱藏或者禁止的字段被排除在外,XML的根元素名稱來自于Axd<document>去掉Axd前綴。我們可以用下面的Job從代碼生成相應(yīng)文檔服務(wù)的XSD:
static void GenerateXSDSchema_Customer(Args _args) {CustCustomer customer;XML xml;XMLDocument xmlDocument;FileName fileName;;// Instantiate the class.customer = new CustCustomer();// Get the document class schema.xml =customer.getSchema();xmlDocument = XMLDocument::newXML(xml);// Save the schema to a file.fileName = "c:\\XSDSchema_Customer.xsd";new FileIoPermission(fileName, 'rw').assert();xmlDocument.save(fileName);CodeAccessPermission::revertAssert(); }在生成的Schema中我們可以看到AxdCustomer類被映射為complexType類型,其下包含的元素是從AxdCustomer的parmXXX方法去掉parm而來;Query中的表Custtable也映射為complexType類型,名稱為AxdEntity_CustTable,包含的元素來自于表字段,只有那些包含在AxCustTable.parmXXX方法的字段才會出現(xiàn)在XSD中。更詳盡的字段類型到XSD的單元的映射關(guān)系參見http://msdn.microsoft.com/EN-US/library/aa636469.aspx。要說明的是上面得到的文檔服務(wù)的完整XSD,而我們在端口配置窗口中“View schema”看到的XSD是完整XSD的子集,在“Document data policies”窗口我們可以手工使能或者禁止某個字段,這只是對當(dāng)期所配置的AIF端口有效。
XSD描述了XML消息的格式,下面是CustCustomerService.read操作得到的XML序列化結(jié)果樣例(省略部分內(nèi)容):
<?xml version="1.0" encoding="UTF-8" ?> - <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"> - <Header><MessageId>{93FE7B5F-99E6-45D6-BAA5-654699EFF0EA}</MessageId> <Action>http://schemas.microsoft.com/dynamics/2008/01/services/CustomerService/read</Action> <RequestMessageId>{E983D78F-0011-47B7-8716-F8B64D120EF6}</RequestMessageId> </Header> - <Body>- <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">- <Customer xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Customer"><DocPurpose>Original</DocPurpose> <SenderId>DMO</SenderId> <ValidAsOfDateTime>2012-04-19T19:42:40Z</ValidAsOfDateTime> <ValidTimeStateType>AsOf</ValidTimeStateType> - <CustTable class="entity"><_DocumentHash>261dcc95694f19ee9010b1866237b4a2</_DocumentHash> <AccountNum>4503</AccountNum> <AccountStatement>Always</AccountStatement> <Blocked>No</Blocked> <CashDisc>14D1%</CashDisc> ......<WebSalesOrderDisplay>WebEntered</WebSalesOrderDisplay> - <DirParty xsi:type="AxdEntity_DirParty_DirOrganization" class="entity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><LanguageId>En-us</LanguageId> <Name>3 Company</Name> <NameAlias>3</NameAlias> <PartyNumber>1310</PartyNumber> <RecId>5637145091</RecId> <RecVersion>1</RecVersion> - <DirPartyPostalAddressView class="entity"><Address>522 West 5th Street New York, NY 10032 US</Address> <City>New York</City> ....<ABC>None</ABC> - <OrganizationName class="entity"><Name>3 Company</Name> <RecId>5637144581</RecId> <RecVersion>1</RecVersion> <ValidFrom>2009-06-13T00:17:00Z</ValidFrom> <ValidTo>2154-12-31T23:59:59Z</ValidTo> </OrganizationName></DirParty></CustTable></Customer></MessageParts></Body></Envelope>消息包括封皮Envelope和Header段,Header段的Action指定操作的名稱。有幾點(diǎn)需要說明,注意到Axd類parmXXX被序列化到XML;Query中的表加上了class="entity"屬性;如果使用了Ax<Table>,只有Ax<Table>.parmXXX方法指定的內(nèi)容被序列化,并且由它來讀取驗(yàn)證數(shù)據(jù),否則數(shù)據(jù)直接從數(shù)據(jù)庫表讀出Query中指定的字段。
我們已經(jīng)知道文檔服務(wù)的具體操作是在文檔服務(wù)類中實(shí)現(xiàn),標(biāo)準(zhǔn)的文檔服務(wù)操作包括create、delete、find、findKeys、read、update、getKeys、getChangedKeys。在AOT的Services節(jié)點(diǎn)下我們可以新建一個Service來引用這些操作,進(jìn)而在出入站端口中使用。當(dāng)然不是每一個文檔都需要實(shí)現(xiàn)上述所有的標(biāo)準(zhǔn)服務(wù),此外我們還可以添加自定義的服務(wù)操作,這些自定義服務(wù)操作方法必須定義為public,如果參數(shù)或者返回值是個對象類,那么這個對象類必須實(shí)現(xiàn)AifXmlSerializable接口,如果不是對象類則只有以下幾種元類型被支持:str、?date、?utcdatetime、?guid、?int、?int64、?enum、real、void。如何創(chuàng)建一個自定義服務(wù)可以參見http://msdn.microsoft.com/EN-US/library/aa607052.aspx。
在findKeys、update、read等方法中用到類AifEntityKeyList,它表示的是一個鍵值對,比如我們要讀取一個Customer的信息,傳入的鍵值對可能是AccountNum=5407。如果我們在自定義的方法中需要返回大量數(shù)據(jù),可以考慮只返回記錄的鍵值對,然后再用read方法根據(jù)鍵值對取出實(shí)際的記錄數(shù)據(jù),這有助于提高性能。
后續(xù)還有更多關(guān)于文檔服務(wù)的內(nèi)容......
轉(zhuǎn)載于:https://www.cnblogs.com/duanshuiliu/archive/2013/01/30/2882581.html
總結(jié)
以上是生活随笔為你收集整理的[AX]AX2012 AIF(二):文档服务编程模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flex与Java通信之HttpServ
- 下一篇: [Java]关于throw,throws