﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Tinysun-随笔分类-Microsoft Dynamic AX</title><link>http://www.blogjava.net/tinysun/category/43874.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 04 Feb 2010 22:28:58 GMT</lastBuildDate><pubDate>Thu, 04 Feb 2010 22:28:58 GMT</pubDate><ttl>60</ttl><item><title>CacheLookup Typa: None, NotInTTS, Found, FoundAndEmpty and EntireTable/ Loading pricedisctable is very slow </title><link>http://www.blogjava.net/tinysun/archive/2010/02/04/311894.html</link><dc:creator>何克勤</dc:creator><author>何克勤</author><pubDate>Thu, 04 Feb 2010 02:31:00 GMT</pubDate><guid>http://www.blogjava.net/tinysun/archive/2010/02/04/311894.html</guid><wfw:comment>http://www.blogjava.net/tinysun/comments/311894.html</wfw:comment><comments>http://www.blogjava.net/tinysun/archive/2010/02/04/311894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tinysun/comments/commentRss/311894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tinysun/services/trackbacks/311894.html</trackback:ping><description><![CDATA[<div class="title">
<div class="title">Record Caching<!----></div>
<!--content type: DocStudio. Transform: devdiv2mtps.xslt.-->
<div id="mainSection">
<div id="mainBody">
<div class="introduction">
<p>Microsoft Dynamics AX database record caching is a performance-enhancing feature that helps avoid database access when it's not strictly necessary. Retrieving database records from memory instead of the database significantly speeds up data access. Caching can reduce the performance penalty for repetitively accessing the same database records. </p>
<p>For an in-depth look at caching and its affect on performance, see Greef, Pontoppidan, et al. 2006. <em>Inside Microsoft Dynamics AX 4.0</em>. 427-461. Redmond: Microsoft Press. </p>
</div>
<div id="ctl00_rs1_mainContentContainer_cpe63053" class="MTPS_CollapsibleRegion">
<div id="ctl00_rs1_mainContentContainer_cpe63053_h" class="CollapseRegionLink"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-left-width: 0px" id="ctl00_rs1_mainContentContainer_cpe63053_i" class="LibC_o" alt="" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" />&nbsp;Types of Caching </div>
<div style="width: auto; display: block; height: auto; overflow: visible" id="ctl00_rs1_mainContentContainer_cpe63053_c" class="MTPS_CollapsibleSection">
<div style="border-bottom: medium none; border-left: medium none; display: block; border-top: medium none; border-right: medium none" class="MTPS_CollapsibleSection"><a id="sectionToggle0"><!----></a>
<p>Caching is transparent to the application; however, it's important to know how caching works to optimize its performance in Microsoft Dynamics AX. Following are the types of caching: </p>
<ul>
    <li>
    <p>Single-record </p>
    <li>
    <p>Set-based </p>
    </li>
</ul>
<p>Single-record caching has the following characteristics: </p>
<ul>
    <li>
    <p>Defined at design time </p>
    <li>
    <p>Moves records to the cache based on the table's <code>CacheLookup</code> property and the type of <code>SELECT</code> statement that is used to retrieve the record </p>
    </li>
</ul>
<p>For more information about record caching, see <a id="ctl00_rs1_mainContentContainer_ctl05" onclick="javascript:Track('ctl00_rs1_mainContentContainer_cpe63053_c|ctl00_rs1_mainContentContainer_ctl05',this);" href="http://msdn.microsoft.com/en-us/library/bb314693.aspx">Single-Record Caching</a>. </p>
<p>Set-based caching has the following characteristics: </p>
<ul>
    <li>
    <p>Defined either at design time or in X++ code </p>
    <li>
    <p>Moves sets of records to the cache </p>
    <li>
    <p>Implemented either through the table's <code>CacheLookup</code> property or in code by using the <code>RecordViewCache</code> class </p>
    </li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="title">1, Single-Record Caching<!----></div>
<!--content type: DocStudio. Transform: devdiv2mtps.xslt.-->
<div id="mainSection">
<div id="mainBody">
<div class="introduction">
<p>Record caching is enabled for a table when all the following statements are true: </p>
<ul>
    <li>
    <p>The <code>CacheLookup</code> property on the table is enabled by setting it to one of the following values: </p>
    <ul>
        <li>
        <p>notInTTS </p>
        <li>
        <p>Found </p>
        <li>
        <p>FoundAndEmpty </p>
        </li>
    </ul>
    <li>
    <p>The table's <code>PrimaryIndex</code> property is set to a unique index that exists on the table. The RecId index does not qualify as a caching index unless you set the table's <code>PrimaryIndex</code> property to this index. </p>
    <li>
    <p>The record buffer <code>disableCache</code> method has not been called with a parameter of <span class="parameter">true</span>. </p>
    </li>
</ul>
<p>The fields in the table's unique index make up the caching key. A record is placed in the cache when the following criteria are met: </p>
<ul>
    <li>
    <p>The table is cached by setting the <code>CacheLookup</code> property to notInTTS, Found, or FoundAndEmpty. </p>
    <li>
    <p>The <code>SELECT</code> statement that selects the records uses an equal operator (==) on the caching key. The fields in the <code>WHERE</code> clause of the <code>SELECT</code> statement match the fields in the index referenced by the table's <code>PrimaryIndex</code> property. </p>
    </li>
</ul>
<p>The table's <code>CacheLookup</code> property defines how and when records are cached as shown in the following table. </p>
<div class="tableSection">
<table style="font-family: Arial; font-size: 10pt">
    <tbody>
        <tr>
            <th>
            <p>CacheLookup Property Value </p>
            </th>
            <th>
            <p>Result </p>
            </th>
        </tr>
        <tr>
            <td>
            <p>None </p>
            </td>
            <td>
            <p>No data is cached or retrieved from the cache for this table. </p>
            <p>This property value should be used for tables that are heavily updated or where it's unacceptable to read outdated data. </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>NotInTTS </p>
            </td>
            <td>
            <p>All successful caching key selects are cached. </p>
            <p>When in a transaction (after ttsBegin), no caches made outside the transaction are used. When inside a transaction, the record is read once from database and subsequently from cache. The record is select-locked when read in a transaction, which ensures that the record cached is not updated while the transaction is active. </p>
            <p>A typical example of the <code>NotInTTS</code> property is the CustTable in the Microsoft Dynamics AX standard application. It's acceptable to read outdated data from the cache outside a transaction, but when data is used for validation or creating references, it is ensured that the data is real-time. </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Found </p>
            </td>
            <td>
            <p>All successful caching key selects are cached. All caching key selects are returned from the cache if the record exists there. A <code>select</code><code>forUpdate</code> in a transaction forces reading from the database and replaces the record in the cache. </p>
            <p>This is typically used for static (lookup) tables, such as Unit, where the record usually exists. </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>FoundAndEmpty </p>
            </td>
            <td>
            <p>All selects on caching keys are cached, including selects that are not returning data. </p>
            <p>All caching key selects are returned from caching if the record exists there, or the record is marked as nonexistent in the cache. A <code>select</code><code>forUpdate</code> in a transaction forces reading from the database and replaces the record in the cache. </p>
            <p>An example of <code>FoundAndEmpty</code> record caching is in the Discount table in the Microsoft Dynamics AX standard application. By default, the Discount table has no records. By using a FoundAndEmpty cache on this table, the keys that are queried for but not found are stored in the cache. Subsequent queries for these same non-existent records can be answered from the cache without a round trip to the database. </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>EntireTable </p>
            </td>
            <td>
            <p>Creates a set-based cache on the server. The entire table is cached as soon as at least one record is selected from the table. </p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>The Found and FoundAndEmpty caches cross transaction boundaries. The NotInTTS cache is newly created inside a transaction. The following code example is from Greef, Pontoppidan, et al. 2006. <em>Inside Microsoft Dynamics AX 4.0</em>. 445. Redmond: Microsoft Press. This example, modified for the purposes of this topic, demonstrates how records are retrieved from the cache when the table's <code>CacheLookup</code> property is set to NotInTTS, and the <code>PrimaryIndex</code> property is set to a unique index on the AccountNum field. </p>
<div id="ctl00_rs1_mainContentContainer_ctl01_other">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/JackyXu1981/admin/javascript:CopyCode('ctl00_rs1_mainContentContainer_ctl01other');"><img class="LibC_copy_off" border="0" alt="" align="center" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" height="9" /> Copy Code</a></div>
</div>
<div dir="ltr">
<pre style="word-wrap: break-word; word-break: break-all" id="ctl00_rs1_mainContentContainer_ctl01other" class="libCScode" space="preserve">static void NotInTTSCache(Args _args)
{
CustTable custTable;
;
// The query looks for records in the cache.
// If records don't exist, the query accesses the database.
select custTable
where custTable.AccountNum == '4000';
// The transaction starts.
ttsbegin;
// The cache is not used. The query accesses the database
// and records are placed in the cache.
select custTable
where custTable.AccountNum == '4000';
// The query uses the database because
// the forupdate keyword is used.
select forupdate custTable
where custTable.AccountNum == '4000';
// The query uses the cache and not the database.
select custTable
where custTable.AccountNum == '4000';
// The query uses the cache because
// the forupdate keyword was used previously.
select forupdate custTable
where custTable.AccountNum == '4000';
// The transaction is committed.
ttscommit;
// The query will use the cache.
select custTable
where custTable.AccountNum == '4000';
}</pre>
</div>
</div>
<p>Reproduced by permission from Greef, Pontoppidan, et al, <em>Inside Microsoft Dynamics AX 4.0</em> (Redmond, WA: Microsoft Press, 2006), 445. </p>
<p>If the table <code>CacheLookup</code> property was set to Found or FoundAndEmpty, the first <code>select</code> statement inside the transaction (after the <code>TTSBegin</code> statement) would retrieve the record from the cache. </p>
</div>
<div id="ctl00_rs1_mainContentContainer_cpe61550" class="MTPS_CollapsibleRegion">
<div id="ctl00_rs1_mainContentContainer_cpe61550_h" class="CollapseRegionLink"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-left-width: 0px" id="ctl00_rs1_mainContentContainer_cpe61550_i" class="LibC_o" alt="" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" />&nbsp;Cache Location </div>
<div style="width: auto; display: block; height: auto; overflow: visible" id="ctl00_rs1_mainContentContainer_cpe61550_c" class="MTPS_CollapsibleSection">
<div style="border-bottom: medium none; border-left: medium none; display: block; border-top: medium none; border-right: medium none" class="MTPS_CollapsibleSection"><a id="sectionToggle0"><!----></a>
<p>Caches are used on both the client and the server. The Microsoft Dynamics AX runtime manages the cache by removing old records when new records are added to the cache. </p>
<h3 class="subHeading"><span style="font-family: Arial; font-size: 10pt">Client Cache</span></h3>
<div class="subsection">
<p>A client-side cache can be used only by the client. The client cache is used when a <code>select</code> is executed from the client tier. If no record is found in the client cache, the client then searches the server cache for the record. If the record isn't located in the server cache, it's retrieved from the database. The maximum number of records maintained in a client cache is 100 records per table for a given company. </p>
</div>
<h3 class="subHeading"><span style="font-family: Arial; font-size: 10pt">Server Cache</span></h3>
<div class="subsection">
<p>A server-side cache can be used by any connection to the server. The server cache is used when a <code>select</code> is executed on the server tier. If no record is found in the cache, it's retrieved from the database. The maximum number of records maintained in a server cache is 2,000 records per table for a given company. </p>
<p>&nbsp;</p>
<div class="title">2, Set-Based Caching<!----></div>
<p><!--content type: DocStudio. Transform: devdiv2mtps.xslt.--></p>
<div id="mainSection">
<div id="mainBody">
<div class="introduction">
<p>In Microsoft Dynamics AX, groups of records can be cached all at once with set-based caching. Set-based caching can be implemented in two ways: </p>
<ul>
    <li>
    <p>At design time, by setting the table's <code>CacheLookup</code> property to <code>EntireTable</code>. </p>
    <li>
    <p>In code, by using the <code>RecordViewCache</code> class. </p>
    </li>
</ul>
</div>
<div id="ctl00_rs1_mainContentContainer_cpe63774" class="MTPS_CollapsibleRegion">
<div id="ctl00_rs1_mainContentContainer_cpe63774_h" class="CollapseRegionLink"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-left-width: 0px" id="ctl00_rs1_mainContentContainer_cpe63774_i" class="LibC_o" alt="" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" />&nbsp;EntireTable Cache </div>
<div style="width: auto; display: block; height: auto; overflow: visible" id="ctl00_rs1_mainContentContainer_cpe63774_c" class="MTPS_CollapsibleSection">
<div style="border-bottom: medium none; border-left: medium none; display: block; border-top: medium none; border-right: medium none" class="MTPS_CollapsibleSection"><a id="sectionToggle0"><!----></a>
<p>When you set a table's <code>CacheLookup</code> property to <code>EntireTable</code>, all the records in the table are placed in the cache after the first select. This type of caching follows the rules of single record caching in which the <code>SELECT</code> statement <code>WHERE</code> clause fields must match those of the unique index defined in the table's <code>PrimaryIndex</code> property. </p>
<p>The EntireTable cache is located on the server and is shared by all connections to the Application Object Server (AOS). If a select is made on the client tier to a table that is EntireTable cached, it first looks in its own cache and then searches the server-side EntireTable cache. An EntireTable cache is created for each table for a given company. If you have two selects on the same table for different companies the entire table is cached twice. </p>
<p>Joins that include an EntireTable cached table are only performed against the cached copy when all tables participating in the join are EntireTable cached. Otherwise a database join is performed. </p>
<div class="alert">
<table style="width: 1023px; font-family: Arial; height: 93px; font-size: 10pt">
    <tbody>
        <tr>
            <th><!--src=[../local/alert_note.gif]--><img alt="Note" src="http://i.msdn.microsoft.com/Bb314630.alert_note(en-US,AX.50).gif" /><strong>Note </strong></th>
        </tr>
        <tr>
            <td>
            <p>Avoid using EntireTable caches for large tables because once the cache size reaches 128 KB the cache is moved from memory to disk. A disk search is much slower than an in-memory search. </p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>For more information about EntireTable caching, see <em>Inside Microsoft Dynamics AX 4.0</em>, Chapter 17. </p>
<h3 class="subHeading"><span style="font-family: Arial; font-size: 10pt">Flushing the Cache</span></h3>
<div class="subsection">
<p>An EntireTable cache is flushed whenever an insert, update, or delete is made to the table. At the same time, the AOS notifies other AOSs that their caches of the same table must be flushed. After the cache is flushed, a subsequent select on the table causes the entire table to be cached again. Therefore, avoid caching any table that's frequently updated. Regardless of when updates are made, EntireTable caches are flushed every 24 hours by the AOS. </p>
</div>
</div>
</div>
</div>
<div id="ctl00_rs1_mainContentContainer_cpe63775" class="MTPS_CollapsibleRegion">
<div id="ctl00_rs1_mainContentContainer_cpe63775_h" class="CollapseRegionLink"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; vertical-align: middle; border-left-width: 0px" id="ctl00_rs1_mainContentContainer_cpe63775_i" class="LibC_o" alt="" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" />&nbsp;RecordViewCache Cache </div>
<div style="width: auto; display: block; height: auto; overflow: visible" id="ctl00_rs1_mainContentContainer_cpe63775_c" class="MTPS_CollapsibleSection">
<div style="border-bottom: medium none; border-left: medium none; display: block; border-top: medium none; border-right: medium none" class="MTPS_CollapsibleSection"><a id="sectionToggle1"><!----></a>
<p>Set-based caching is implemented in code by using the <code>RecordViewCache</code> class. You must first create a record buffer using the <code>nofetch</code> statement and then pass the record buffer to the <code>RecordViewCache</code> class when it's instantiated. </p>
<p>The cache is created on the server and is only accessible by the process that creates the cache object. Once the cache is instantiated, all select statements are issued against the cache, as shown in the following code (from <em>Inside Dynamics AX 4.0</em>, Chapter 17, page 450). </p>
<div id="ctl00_rs1_mainContentContainer_ctl08_other">
<div class="CodeSnippetTitleBar">
<div class="CodeDisplayLanguage"></div>
<div class="CopyCodeButton"><a class="copyCode" href="http://www.cnblogs.com/JackyXu1981/admin/javascript:CopyCode('ctl00_rs1_mainContentContainer_ctl08other');"><img class="LibC_copy_off" border="0" alt="" align="center" src="http://i.msdn.microsoft.com/Global/Images/clear.gif" height="9" /> Copy Code</a></div>
</div>
<div dir="ltr">
<pre style="word-wrap: break-word; word-break: break-all" id="ctl00_rs1_mainContentContainer_ctl08other" class="libCScode" space="preserve">static void RecordViewCache(Args _args)
{
CustTrans       custTrans;
RecordViewCache recordViewCache;
;
// Define records to cache.
select nofetch custTrans
where custTrans.AccountNum == '4000';
// Cache the records.
recordViewCache = new RecordViewCache(custTrans);
// Use cache.
select firstonly custTrans
where custTrans.AccountNum == '4000' &amp;&amp;
custTrans.CurrencyCode == 'USD';
}</pre>
</div>
</div>
<p>Due to concurrency issues, the <code>forUpdate</code> keyword on the instantiating X++ <code>SELECT</code> statement should only be used when all of the records in the result set will be updated. Otherwise it's a better strategy to use <code>select</code><code>forUpdate</code> only for the records that are to be updated. </p>
<p>The <code>RecordViewCache</code> class is used in a select when the select is from a table that's cached, the select statement doesn't participate in a join and the select <code>WHERE</code> clause matches the <code>WHERE</code> clause with which the <code>RecordViewCache</code> was instantiated. </p>
<p>The cache created by the RecordViewCache class stores records in a linked list. Therefore Microsoft Dynamics AX searches the cache sequentially for records that match the search criteria. If the <code>SELECT</code> statement contains an <code>ORDER&nbsp;BY</code> clause, a temporary index is placed on the cache and the runtime uses the index when searching records.</p>
<p>The <span class="docEmphasis">EntireTable</span> Cache</p>
<p class="docText"><a name="iddle1772"></a><a name="iddle1885"></a>In addition to the three caching methods described so far, a fourth caching option can be set on a table. This option is the <span class="docEmphasis">EntireTable</span>, which enables a set-based cache. The option causes the AOS to mirror the table in the database by selecting all records in the table and inserting them into a temporary table when any record from the table is selected for the first time. The first process to read from the table could therefore experience a longer response time because the application runtime reads all records from the database. Subsequent <span class="docEmphasis">select</span> queries then read from the entire-table cache instead of from the database.</p>
<p class="docText">A temporary table is usually local to the process that uses it, but the entire-table cache is shared among all processes that access the same AOS. Each company (as defined by the <span class="docEmphasis">DataAreaId</span> field) has an entire-table cache, so two processes requesting records from the same table from different companies use different caches, and both could experience a longer response time to instantiate the entire-table cache.</p>
<p class="docText">The entire-table cache is a server-side cache only. When requesting records from the client tier on a table that is entire-table cached, the table behaves as a <span class="docEmphasis">Found</span> cached table. If a request for a record is made on the client tier that qualifies for searching the record cache, the client first searches the local <span class="docEmphasis">Found</span> cache. If the record is not found, the client calls the AOS to search the entire-table cache. When the application runtime returns the record to the client tier, it inserts the record into the client-side <span class="docEmphasis">Found</span> cache.</p>
<p class="docText">The entire-table cache is not used when executing a <span class="docEmphasis">select</span> statement by which an entire-table-cached table is joined to a table that is not entire-table cached. In this situation, the entire <span class="docEmphasis">select</span> statement is parsed to the database. However, when <span class="docEmphasis">select</span> statements are made that access only the single entire-table cached table, or when joining other entire-table cached tables, the entire-table cache is used.</p>
<p class="docText">The Dynamics AX application runtime flushes the entire-table cache when records are inserted, updated, or deleted in the table. The next process, which selects records from the table, suffers a degradation in performance because it must re-read the entire table into cache. In addition to flushing its own cache, the AOS that executes the insert, update, or delete also informs other AOSs in the same installation that they must flush their caches on the same table. This prevents old and invalid data from being cached for too long in the entire Dynamics AX application environment. In addition to this flushing mechanism, the AOS flushes all the entire-table caches every 24 hours.</p>
<p class="docText"><a name="iddle2375"></a><a name="iddle2599"></a>Because of the flushing that results when modifying records in a table that has been entire-table cached, you should avoid setting up entire-table caches on frequently updated tables. Rereading all records into the cache results in a performance loss, which could outweigh the performance gain achieved by caching records on the server tier and avoiding round trips to the database tier. The entire-table cache setting on a specific table can therefore be overwritten at run time when you configure the Dynamics AX application.</p>
<p class="docText">Even if the records in a table are fairly static, you might achieve better performance by not using the entire-table cache if the number of records in the table is large. Because the entire-table cache uses temporary tables, it changes from an in-memory structure to a file-based structure when the table uses more than 128 kilobytes (KB) of memory. This results in performance degradation during record searches. The database search engines have also evolved over time and are faster than the ones implemented in the Dynamics AX application runtime. It might be faster to let the database search for the records than to set up and use an entire-table cache, even though a database search involves round trips to the database tier.</p>
<p class="docText">&nbsp;</p>
<p class="docText">For PriceDiscTable included Trade Agreement information. When you create a Sales/Purchase line, it become very slow when your pricedisctable has 30000 records because the table's cache (cache lookup) type is entiretable. It is possible to change cache type to Found.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<img src ="http://www.blogjava.net/tinysun/aggbug/311894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tinysun/" target="_blank">何克勤</a> 2010-02-04 10:31 <a href="http://www.blogjava.net/tinysun/archive/2010/02/04/311894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Axapta当中的RunOn属性</title><link>http://www.blogjava.net/tinysun/archive/2010/02/03/311832.html</link><dc:creator>何克勤</dc:creator><author>何克勤</author><pubDate>Wed, 03 Feb 2010 10:53:00 GMT</pubDate><guid>http://www.blogjava.net/tinysun/archive/2010/02/03/311832.html</guid><wfw:comment>http://www.blogjava.net/tinysun/comments/311832.html</wfw:comment><comments>http://www.blogjava.net/tinysun/archive/2010/02/03/311832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/tinysun/comments/commentRss/311832.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/tinysun/services/trackbacks/311832.html</trackback:ping><description><![CDATA[<p>RunOn，顾名思义，就是指Object在那一层上面运行，客户端，还是服务器端？当然，前提是要在三层结构下面。Axapta当中与RunOn有关的，大概在以下这几个地方：</p>
<p>相关的Object，如Form, Report, Class等，Class当中的静态方法，以及MenuItem。</p>
<p>Form和Report是不能设置RunOn属性的，Form只能是运行在客户端，而Report则是由MenuItem所决定的，因为它的RunOn属性其实是被设为(Always)Called from的。当然，假如Report不用MenuItem指定激活的话，如直接在AOT当中用右键打开(Open)，那就肯定是在客户端生成了。</p>
<p>那么剩下可以讨论的就是Class的RunOn属性，和Class当中的静态方法了。</p>
<p>静态方法，由它本身的modifier所决定。不写的情况下，默认为client server（可显式声明，一般情况下不用），也就是等于Called from，在哪里被调用就在哪里运行。</p>
<p>Class本身的RunOn属性是具有最高优先级的，只有当设置为Called from的时候，才会取决于MenuItem中的RunOn属性。还有一种情况就是，很多Class的main方法也指定了modifier，这个时候main方法的modifier比MenuItem更有优先权来决定Class运行的位置。</p>
<p>也就是说Class的RunOn属性 优先于 main方法的modifier 优先于 MenuItem的RunOn属性。</p>
<p>那么我们再来讨论这个RunOn属性的作用。</p>
<p>我们知道，在Axapta三层结构体系当中，不同层之间的调用，无论是方法，还是数据的交换，都会造成运行效率的降低。所以我们必须要尽可能减少不同层之间的调用。譬如说，某个Class具体的作用是进行数据运算，那么这个时候我们把它放在Client端运行是非常不合理的。因为这种情况下它需要和database进行大量的数据交换（中间需要通过AOS），所以我们就需要强制性的把它指定运行在AOS上，这样也可以减少了网内部的带宽消耗，更可以充分利用三层结构的优点，降低了客户端机器的负载。</p>
<p>然后还是有一个Best Practice原则，就是尽量把RunOn设置在MenuItem，而不要指定在Class本身的属性上面（尽量默认为Called from）。这样做的好处在于，可以灵活运用，因为某一个Class可以在不同的情况下，被指定运行在不同层上。开发人员只需要更改和使用不同的MenuItem，就可以达到这种效果。这也是Axapta里面所谓的API原则，尽量都通过MenuItem去激活和指定Object的运行状态。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/junevoful/archive/2006/01/06/572496.aspx</p>
<img src ="http://www.blogjava.net/tinysun/aggbug/311832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/tinysun/" target="_blank">何克勤</a> 2010-02-03 18:53 <a href="http://www.blogjava.net/tinysun/archive/2010/02/03/311832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>