Skip to content

Instantly share code, notes, and snippets.

@FransBouma
Created June 12, 2014 08:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FransBouma/5e7031fe557df4b5b688 to your computer and use it in GitHub Desktop.
Save FransBouma/5e7031fe557df4b5b688 to your computer and use it in GitHub Desktop.
Do Contains calls in chunks. Original by Marc Gravell. Fixed for LLBLGen Pro
public static class QueryableChunked
{
public static IEnumerable<T> InRange<T, TValue>(this IQueryable<T> source,
System.Linq.Expressions.Expression<Func<T, TValue>> selector, int blockSize,
IEnumerable<TValue> values)
{
MethodInfo method = null;
foreach(MethodInfo tmp in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static))
{
if(tmp.Name == "Contains" && tmp.IsGenericMethodDefinition && tmp.GetParameters().Length == 2)
{
method = tmp.MakeGenericMethod(typeof(TValue));
break;
}
}
if(method == null) throw new InvalidOperationException("Unable to locate Contains");
foreach(TValue[] block in values.GetBlocks(blockSize))
{
// INVOKE not necessary, reuse selector
//var row = System.Linq.Expressions.Expression.Parameter(typeof(T), "row");
//var member = System.Linq.Expressions.Expression.Invoke(selector, row);
//var keys = System.Linq.Expressions.Expression.Constant(block, typeof(TValue[]));
//var predicate = System.Linq.Expressions.Expression.Call(method, keys, member);
//var lambda = System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(predicate, row);
var keys = System.Linq.Expressions.Expression.Constant(block, typeof(TValue[]));
var predicate = System.Linq.Expressions.Expression.Call(method, keys, selector.Body);
var lambda = System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(predicate, selector.Parameters[0]);
foreach(T record in source.Where(lambda))
{
yield return record;
}
}
}
public static IEnumerable<T[]> GetBlocks<T>(this IEnumerable<T> source, int blockSize)
{
List<T> list = new List<T>(blockSize);
foreach(T item in source)
{
list.Add(item);
if(list.Count == blockSize)
{
yield return list.ToArray();
list.Clear();
}
}
if(list.Count > 0)
{
yield return list.ToArray();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment