• [AX]AX2012 AIF(十):Query service系统服务中处理大数据集


    在查询服务中可以使用分页(pageing)和流(Streaming)两种方式处理查询返回的大量数据。

    • 分页:客户端程序可以传入一个page对象,由它分页返回直至最大记录数上限的数据(默认每个数据源25000条记录)。分页在三种查询服务(静态查询、用户自定义查询、动态查询)中都可以使用,如果传入NULL的page对象,则直接返回直至记录数上限的数据。

    分页由分基于位置的分页和基于值的分页两种方式,基于值的分页又分标准值分页、顶级数据源值分页和高级值分页三种,下面用实例代码来看看它们具体如何使用。

    示例一:

    using System;
    using System.Data;
    using System.Globalization;
    using TestQueryServicePosPage.ServiceReference1;
    
    namespace TestQueryServicePosPage
    {
        class Program
        {
            static void Main()
            {
                var client = new QueryServiceClient();
    
                var i = 0;
                DataSet dataSet;
                Paging paging = new PositionBasedPaging { StartingPosition = 1, NumberOfRecordsToFetch = 10 };
    
                do
                {
                    // Call the CustTable query using the query service.
                    dataSet = client.ExecuteStaticQuery("CustTable", ref paging);
    
                    // Code to perform operations on the data returned.
                    Console.WriteLine("Query service call: " + i.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTable: " + dataSet.Tables[0].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTrans: " + dataSet.Tables[1].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTransOpen: " + dataSet.Tables[2].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    i++;
                }
                // Check if the last call returned any data. If so, then this is the next page of data.
                while (dataSet.Tables[0].Rows.Count > 0);
    
                Console.ReadLine();
            }
        }
    }

    在上面的例子中使用了基于位置的分页,每个数据源返回的记录每页不超过10个,通过传入相同的Paging对象多次执行查询顶级数据源以获取所有数据,如果需要按照一定顺序返回记录,需要在Query中显式的指定排序字符串。

    示例二:

    var client = new QueryServiceClient();
    
                var i = 0;
                Paging paging = new ValueBasedPaging() { RecordLimit = 10 };
    
                do
                {
                    // Call the CustTable query using the query service.
                    var dataSet = client.ExecuteStaticQuery("CustTable", ref paging);
    
                    // Code to perform operations on the data returned.
                    Console.WriteLine("Query service call: " + i.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTable: " + dataSet.Tables[0].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTrans: " + dataSet.Tables[1].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTransOpen: " + dataSet.Tables[2].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    i++;
                }
                // Check if the returned bookmark is NULL. If so, there is no more data to be returned.
                while (((ValueBasedPaging)paging).Bookmark != null);

    上面的例子演示如何使用标准值分页,通过查询ValgeBasedPaging对象的Bookmark检查是否还有下一页的数据,没个数据源都返回不超过RecordLimit指定的记录数。

    示例三:

    var client = new QueryServiceClient();
    
                var i = 0;
                Paging paging = new TopLevelValueBasedPaging() { RecordLimit = 25, LimitTopLevelDataSourcesOnly = true };
    
                do
                {
                    // Call the CustTable query using the query service.
                    var dataSet = client.ExecuteStaticQuery("CustTable", ref paging);
    
                    // Code to perform operations on the data returned.
                    Console.WriteLine("Query service call: " + i.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTable: " + dataSet.Tables[0].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTrans: " + dataSet.Tables[1].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTransOpen: " + dataSet.Tables[2].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    i++;
                }
                // Check if the last call returned any data. If so, then this is the next page of data.
                while (((ValueBasedPaging)paging).Bookmark != null);

    上面的例子演示级记录值分页的使用,参数LimitTopLevelDataSourcesOnly设为true时顶级数据源只返回RecordLimit指定的记录数,子级数据源则返回最大记录数上限的记录数;如果LimitTopLevelDataSourcesOnly设为false,则所有数据源返回RecordLimit指定记录数的数据源记录,这和标准值分页是一样的。

    示例四:

    var client = new QueryServiceClient();
    
                var i = 0;
                var advPaging = new AdvancedValueBasedPaging();
                Paging paging = advPaging;
    
                advPaging.RecordLimits = new[] {
                    new DataSourceRecordLimit() { DataSourceName = "CustTable", RecordLimit = 2 },
                    new DataSourceRecordLimit() { DataSourceName = "CustTrans", RecordLimit = 10 },
                    new DataSourceRecordLimit() { DataSourceName = "CustTransOpen", RecordLimit = 10 }};
    
                do
                {
                    // Call the CustTable query using the query service.
                    var dataSet = client.ExecuteStaticQuery("CustTable", ref paging);
    
                    // Code to perform operations on the data returned.
                    Console.WriteLine("Query service call: " + i.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTable: " + dataSet.Tables[0].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTrans: " + dataSet.Tables[1].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    Console.WriteLine("Number of Records in CustTransOpen: " + dataSet.Tables[2].Rows.Count.ToString(CultureInfo.InvariantCulture));
                    i++;
                }
                // Check if the last call returned any data. If so, then this is the next p

    上面的例子演示高级值分页的使用,在高级值分页中可以对每个数据源设置返回记录数的限制。

    在实际测试中以上的例子和预期的结果都有差异,为了简化测试,这里修改一下查询“CustTable”为:顶级数据源为表CustTable(包含39条记录),CustTable下包含表CustTrans(只有2条记录,分别对应2条CustTable的记录),子级CustTrans和父级CustTable数据源的关系分三种情况,一是Relation=No,两者无关联;二是Relation=Yes,FetchMode=1:1;三是Relations=Yes,FetchMode=1:n,测试结果如下:

      样例一:基于位置分页 样例二:标准值分页 样例三:顶级记录值分页 样例四:高级值分页
    Relation=No

    NumberOfRecordsToFetch=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页78次

    NumberOfRecordsToFetch=2:每次CustTable返回1条记录,CustTrans返回2条记录,分页39次

    NumberOfRecordsToFetch=10:每次CustTable返回5条记录,CustTrans返回2条记录,分页8次

    NumberOfRecordsToFetch=39:每次CustTable返回20条记录,CustTrans返回2条记录,分页2次

    RecordLimit=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页78次

    RecordLimit=2:每次CustTable返回2条记录,CustTrans返回2条记录,分页20次

    RecordLimit=10:每次CustTable返回5条记录,CustTrans返回2条记录,分页8次

    RecordLimit=39:每次CustTable返回20条记录,CustTrans返回2条记录,分页2次

    RecordLimit=1,LimitTopLevelDataSourcesOnly = true:每次CustTable返回1条记录,CustTrans返回2条记录,分页39次

    RecordLimit=2LimitTopLevelDataSourcesOnly = true:每次CustTable返回2条记录,CustTrans返回2条记录,分页20次

    RecordLimit=10LimitTopLevelDataSourcesOnly = true:每次CustTable返回10条记录,CustTrans返回2条记录,分页4次

    RecordLimit=39LimitTopLevelDataSourcesOnly = true:每次CustTable返回39条记录,CustTrans返回2条记录,分页1次

    LimitTopLevelDataSourcesOnly = false的情况和标准值分页相同

    CustTable.RecordLimit=1,CustTrans.RecordLimit=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页78次

    CustTable.RecordLimit=1,CustTrans.RecordLimit=2:每次CustTable返回1条记录,CustTrans返回2条记录,分页39次

    CustTable.RecordLimit=2,CustTrans.RecordLimit=2:每次CustTable返回2条记录,CustTrans返回1条记录,分页20次

    CustTable.RecordLimit=10,CustTrans.RecordLimit=2:每次CustTable返回10条记录,CustTrans返回2条记录,分页4次

    CustTable.RecordLimit=10,CustTrans.RecordLimit=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页78次

    Relation=Yes,FetchMode=1:1 NumberOfRecordsToFetch=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页2次

    NumberOfRecordsToFetch=2:每次CustTable返回2条记录,CustTrans返回2条记录,分页1次

    NumberOfRecordsToFetch=10:每次CustTable返回2条记录,CustTrans返回2条记录,分页1次

    NumberOfRecordsToFetch=39:每次CustTable返回2条记录,CustTrans返回2条记录,分页1次

    同样例一,Relation=Yes,FetchMode=1:1 同样例一,Relation=Yes,FetchMode=1:1  

    CustTable.RecordLimit=1,CustTrans.RecordLimit=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页2次

    CustTable.RecordLimit=1,CustTrans.RecordLimit=2:每次CustTable返回1条记录,CustTrans返回1条记录,分页2次

    CustTable.RecordLimit=2,CustTrans.RecordLimit=2:每次CustTable返回2条记录,CustTrans返回2条记录,分页1次

    CustTable.RecordLimit=10,CustTrans.RecordLimit=2:每次CustTable返回2条记录,CustTrans返回2条记录,分页1次

    CustTable.RecordLimit=10,CustTrans.RecordLimit=1:每次CustTable返回1条记录,CustTrans返回1条记录,分页2次

    Relation=Yes,FetchMode=1:n  同Relation=Yes,FetchMode=1:1  同样例一,Relation=Yes,FetchMode=1:1 同样例一,Relation=Yes,FetchMode=1:1  同上

    从以上得出的结论是如果设置父子数据源关系连接,无论是1:1还是1:n的取值方式,最终都只返回父记录的2条记录,这和我们想要的left join效果是不一致的,或者说分页就不支持1:n连接。其次可以看出值分页的recordlimit是在单个数据源上应用,而位置分页的NumberOfRecordsToFetch是应用在每次父子数据源起来的记录总数。上面的结果只是2级2个数据源的情况,如果更复杂些的Query不知道会是什么样的结果,总之,分页的结果不像MSDN说的那样确定,使用的时候还是依据具体的数据自行调试处理吧。

    流:可以使用ExecuteStreamedQuery的ExecuteStreamedQuery()和ExecuteStreamedDynamicQuery()方法从自定义查询或者动态查询中返回一个Stream类型的流对象,但是如何从这个Stream中分解出记录的数据MSDN上没有说明,搜遍网络也没有找到有用的信息,等着微软更新再说吧。

      

  • 相关阅读:
    ***25 k个一组反转链表
    24 交换链表中相连的节点
    19 删除链表倒数第N个节点
    2 两数相加
    23 合并K个有序链表
    21 合并两个有序链表
    114 判断一个链表是否存在环并返回环起点
    141 链表是否存在环
    160 寻找链表交点
    92 指定区间链表逆置
  • 原文地址:https://www.cnblogs.com/duanshuiliu/p/2947751.html
Copyright © 2020-2023  润新知