public class BaseQuery<T> : IQueryable<T>, IQueryable, IEnumerable<T>, IEnumerable, IOrderedQueryable<T>, IOrderedQueryable
{
private Expression expression = null;
private QueryTranslatorProvider<T> provider = null;
public BaseQuery(IQueryable source)
{
var e = Expression.Constant(source);
var p = new QueryTranslatorProvider<T>(source);
Initial(p, e);
}
public BaseQuery(IQueryable source, Expression e)
{
if (e == null) throw new ArgumentNullException("e");
var p = new QueryTranslatorProvider<T>(source);
Initial(p, e);
}
public void Initial(QueryTranslatorProvider<T> p, Expression e)
{
expression = e;
provider = p;
}
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)provider.ExecuteEnumerable(this.expression)).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return provider.ExecuteEnumerable(this.expression).GetEnumerator();
}
public Type ElementType
{
get { return typeof(T); }
}
public Expression Expression
{
get { return expression; }
}
public IQueryProvider Provider
{
get { return provider; }
}
}
public class QueryTranslator<T> : BaseQuery<T> where T : class
{
public QueryTranslator(IQueryable source, Expression e, ObjectSet<T> objectSet)
: base(source, e)
{
ObjectSet = objectSet;
}
public QueryTranslator(IQueryable source, ObjectSet<T> objectSet)
: base(source)
{
ObjectSet = objectSet;
}
public ObjectSet<T> ObjectSet
{
get;
private set;
}
}
public class QueryTranslatorProvider<T> : ExpressionVisitor, IQueryProvider
{
internal IQueryable source;
public QueryTranslatorProvider(IQueryable source)
{
if (source == null) throw new ArgumentNullException("source");
this.source = source;
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
if (expression == null) throw new ArgumentNullException("expression");
return new BaseQuery<TElement>(source, expression) as IQueryable<TElement>;
}
public IQueryable CreateQuery(Expression expression)
{
if (expression == null) throw new ArgumentNullException("expression");
Type elementType = expression.Type.GetGenericArguments().First();
IQueryable result = (IQueryable)Activator.CreateInstance(typeof(BaseQuery<>).MakeGenericType(elementType),
new object[] { source, expression });
return result;
}
public TResult Execute<TResult>(Expression expression)
{
if (expression == null) throw new ArgumentNullException("expression");
object result = (this as IQueryProvider).Execute(expression);
return (TResult)result;
}
public object Execute(Expression expression)
{
if (expression == null) throw new ArgumentNullException("expression");
Expression translated = this.Visit(expression);
return source.Provider.Execute(translated);
}
internal IEnumerable ExecuteEnumerable(Expression expression)
{
if (expression == null) throw new ArgumentNullException("expression");
Expression translated = this.Visit(expression);
return source.Provider.CreateQuery(translated);
}
#region Visitors
protected override Expression VisitConstant(ConstantExpression c)
{
// fix up the Expression tree to work with EF again
if (c.Type == typeof(BaseQuery<T>))
{
return source.Expression;
}
else
{
return base.VisitConstant(c);
}
}
#endregion
}
public static QueryTranslator<Baby> ObjectSet()
{
Guid tenantId = ContextDTO.Current.LoginTenantId;
ObjectSet<Baby> objectSet = Baby.ObjectSet<Baby>();
var query = new QueryTranslator<Baby>(objectSet.Where(b => b.TenantId == tenantId), objectSet);
return query;
}