Prefetch with DataReader? *

Posts   
 
    
Ian avatar
Ian
User
Posts: 511
Joined: 01-Apr-2005
# Posted on: 16-Apr-2008 13:37:06   

(Title should read 'Prefetch') frowning

Hi,

Is it possible to...

a) Get entity instances from a DataReader b) Use prefetch with a DataReader

Cheers, Ian.

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 16-Apr-2008 16:02:46   

Get entity instances from a DataReader

Yes, please read the following section in the manual: Using the generated code -> SelfServicing/Adapter -> Fetching DataReaders and projections

b) Use prefetch with a DataReader

No, PrefetchPaths are only used with Entities and EntityColllections.

Ries
User
Posts: 46
Joined: 23-Aug-2006
# Posted on: 18-Apr-2009 19:33:32   

I needed a forward-only entity reader to traverse a long resultset for reporting purposes. Because I need a large prefetch path, I've created a simulated IDataReader using paging. Works good and fast.

Below is how to use it, hope this helps anyone.

Ries



      /// Fetches all the entities in the giveing query, using paging. Useful to prevent loading all data at once
      /// http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=15146&HighLight=1
      var ordersQuery = from o in PPPMetaData.Order
                        join p in PPPMetaData.VwReportingPreselectOrders on o.OrderId equals p.OrderID
                        where (p.ArrivalHandlingStationID == handlingStation.StationId || p.DepartureHandlingStationID == handlingStation.StationId)
                        && ((p.MostActualArrivalTime >= fromTimeUtc && p.MostActualArrivalTime < beforeTimeUtc)
                            || (p.MostActualDepartureTime >= fromTimeUtc && p.MostActualDepartureTime < beforeTimeUtc))
                        select o;

      ordersQuery = ordersQuery.WithPath(DetailsPath());

      var orders = new EntityReader<OrderEntity>(this.context, ordersQuery);

      foreach (var order in orders)
      {
         // .. use the order
      }


This is the implementation:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SD.LLBLGen.Pro.ORMSupportClasses;
using PPPDataLib.HelperClasses;

namespace PPPBusLib
{
  /// <summary>
  /// This reads entities one page at a time, to prevent using very much memory for large results set
  /// it acts a forward only cursor
  /// </summary>
  public class EntityReader<T> : PPPBusinessObject, IEnumerable<T> where T : EntityBase2, IEntity2
  {
    const int DEFAULT_PAGESIZE = 250; 
    private IQueryable<T> query;
    private int pageSize = DEFAULT_PAGESIZE;

    public EntityReader(PPPBusinessContext context, IQueryable<T> query) : base(context)
    {
      this.query = query;
    }

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
      return new EntityReaderEnumerator<T>(context, query, pageSize);
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return new EntityReaderEnumerator<T>(context, query, pageSize);
    }

    #endregion
  }

  public class EntityReaderEnumerator<T> : PPPBusinessObject, IEnumerator<T> where T : EntityBase2, IEntity2
  {
    private IQueryable<T> query;
    private int pageSize;
    private int currentPage;
    IEnumerator<T> pageEnumerator;

    public EntityReaderEnumerator(PPPBusinessContext context, IQueryable<T> query, int pageSize) : base(context)
    {
      this.query = query;
      this.pageSize = pageSize;
      this.currentPage = 0;
    }

    #region IEnumerator<T> Members

    public T Current
    {
      get { return this.pageEnumerator.Current; }
    }

    #endregion

    #region IDisposable Members

    public void Dispose()
    {
    }

    #endregion

    #region IEnumerator Members

    object System.Collections.IEnumerator.Current
    {
      get { return this.pageEnumerator.Current; }
    }

    public bool MoveNext()
    {
      if (this.pageEnumerator == null)
        FetchNextPage();
    
      bool hasMore = this.pageEnumerator.MoveNext();
      if (!hasMore)
      {
        FetchNextPage();
        hasMore = this.pageEnumerator.MoveNext();
      }

      return hasMore;
    }

    public void Reset()
    {
      this.currentPage = 0;
      this.pageEnumerator = null;
    }

    #endregion

    // http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=15146&HighLight=1
    private void FetchNextPage()
    {
      var pagingQuery = this.query.Skip(this.currentPage * this.pageSize).Take(this.pageSize);
      var currentPageData = Execute<EntityCollection<T>>(pagingQuery);
      this.pageEnumerator = currentPageData.GetEnumerator();
      this.currentPage++;
    }
  }
}