//---------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
namespace System.Data.Objects.ELinq
{
using System;
using System.Collections.Generic;
using System.Data.Objects.Internal;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
///
/// LINQ query provider implementation.
///
internal sealed class ObjectQueryProvider : IQueryProvider
{
// Although ObjectQuery contains a reference to ObjectContext, it is possible
// that IQueryProvider methods be directly invoked from the ObjectContext.
// This requires having a separate field to store ObjectContext reference.
private readonly ObjectContext _context;
private readonly ObjectQuery _query;
///
/// Constructs a new provider with the given context. This constructor can be
/// called directly when initializing ObjectContext or indirectly when initializing
/// ObjectQuery.
///
/// The ObjectContext of the provider.
internal ObjectQueryProvider(ObjectContext context)
{
Debug.Assert(null != context, "context must be given");
_context = context;
}
///
/// Constructs a new provider with the given ObjectQuery. This ObjectQuery instance
/// is used to transfer state information to the new ObjectQuery instance created using
/// the private CreateQuery method overloads.
///
///
internal ObjectQueryProvider(ObjectQuery query)
: this(query.Context)
{
Debug.Assert(null != query, "query must be given");
_query = query;
}
///
/// Creates a new query instance using the given LINQ expresion.
/// The current query is used to produce the context for the new query, but none of its logic
/// is used.
///
/// Element type for query result.
/// LINQ expression forming the query.
/// ObjectQuery implementing the expression logic.
IQueryable IQueryProvider.CreateQuery(Expression expression)
{
EntityUtil.CheckArgumentNull(expression, "expression");
if (!typeof(IQueryable).IsAssignableFrom(expression.Type))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.ELinq_ExpressionMustBeIQueryable, "expression");
}
ObjectQuery query = CreateQuery(expression);
return query;
}
///
/// Executes the given LINQ expression returning a single value, or null if the query yields
/// no results. If the return type is unexpected, raises a cast exception.
/// The current query is used to produce the context for the new query, but none of its logic
/// is used.
///
/// Type of returned value.
/// Expression to evaluate.
/// Single result from execution.
S IQueryProvider.Execute(Expression expression)
{
EntityUtil.CheckArgumentNull(expression, "expression");
ObjectQuery query = CreateQuery(expression);
return ExecuteSingle(query, expression);
}
///
/// Creates a new query instance using the given LINQ expresion.
/// The current query is used to produce the context for the new query, but none of its logic
/// is used.
///
/// Expression forming the query.
/// ObjectQuery instance implementing the given expression.
IQueryable IQueryProvider.CreateQuery(Expression expression)
{
EntityUtil.CheckArgumentNull(expression, "expression");
if (!typeof(IQueryable).IsAssignableFrom(expression.Type))
{
throw EntityUtil.Argument(System.Data.Entity.Strings.ELinq_ExpressionMustBeIQueryable, "expression");
}
// Determine the type of the query instance by binding generic parameter in Query<>.Queryable
// (based on element type of expression)
Type elementType = TypeSystem.GetElementType(expression.Type);
ObjectQuery query = CreateQuery(expression, elementType);
return query;
}
///
/// Executes the given LINQ expression returning a single value, or null if the query yields
/// no results.
/// The current query is used to produce the context for the new query, but none of its logic
/// is used.
///
/// Expression to evaluate.
/// Single result from execution.
object IQueryProvider.Execute(Expression expression)
{
EntityUtil.CheckArgumentNull(expression, "expression");
ObjectQuery query = CreateQuery(expression, expression.Type);
IEnumerable