Esempio n. 1
0
        /// <summary>
        /// Gets a page of size pageSize items, inside a db from dbFactory, and passes that to foreachBody(page, db).
        ///
        /// Then closes the DbContext to keep EF from freaking out on long jobs, and does the above steps again.
        ///
        /// Turns out to be the best way to handle processing a lot of items in EF. As an extra tweak, set a dirty flag at the top of the
        /// loop body you pass in, flag it when you change anything, and call .SaveChanges() just the once as the loop body is ending if
        /// the flag is set.
        /// </summary>
        /// <typeparam name="TDb"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="pageSize"></param>
        /// <param name="dbFactory"></param>
        /// <param name="query"></param>
        /// <param name="foreachBody">The body you'd normally place in a foreach loop for pages of items.</param>
        public static void PagesOf <TDb, TModel>(int pageSize, BaseDbFactory <TDb> dbFactory, Func <TDb, IOrderedQueryable <TModel> > query, Action <IEnumerable <TModel>, TDb> foreachBody)
            where TDb : DbContext, new()
        {
            int length = pageSize;

            for (int page = 0; length == pageSize; page++)
            {
                using (var db = dbFactory.NewDb())
                {
                    var items = query(db).Skip(page * pageSize).Take(pageSize).ToArray();
                    foreachBody(items, db);
                    length = items.Length;
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Pages through items, and detaches from the DbContext for each page; the body of your foreach loop will execute detached, meaning
        /// no lazy loading or other EF access is possible - only the detached objects as-is are readable (no virtual navigation properties)
        /// and no db is available for actions like .SaveChanges();
        /// </summary>
        /// <typeparam name="TDb"></typeparam>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="pageSize"></param>
        /// <param name="dbFactory"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public static IEnumerable <TModel> EnumeratePagedDetached <TDb, TModel>(int pageSize, BaseDbFactory <TDb> dbFactory, Func <TDb, IOrderedQueryable <TModel> > query)
            where TDb : DbContext, new()
        {
            int length = pageSize;

            for (int page = 0; length == pageSize; page++)
            {
                TModel[] items;
                using (var db = dbFactory.NewDb())
                {
                    items = query(db).Skip(page * pageSize).Take(pageSize).ToArray();
                }

                foreach (var item in items)
                {
                    yield return(item);
                }

                length = items.Length;
            }
        }