private DbExpression TranslateInlineQueryOfT(ObjectQuery inlineQuery)
{
if (!ReferenceEquals(_funcletizer.RootContext, inlineQuery.QueryState.ObjectContext))
{
throw new NotSupportedException(Strings.ELinq_UnsupportedDifferentContexts);
}
// Check if the inline query has been encountered so far. If so, we don't need to
// include its parameters again. We do however need to translate it to a new
// DbExpression instance since the expressions may be tagged with span information
// and we don't want to mistakenly apply the directive to the wrong part of the query.
if (null == _inlineEntitySqlQueries)
{
_inlineEntitySqlQueries = new HashSet<ObjectQuery>();
}
var isNewInlineQuery = _inlineEntitySqlQueries.Add(inlineQuery);
// The ObjectQuery should be Entity-SQL-based at this point. All other query types are currently
// inlined.
var esqlState = (EntitySqlQueryState)inlineQuery.QueryState;
// We will produce the translated expression by parsing the Entity-SQL query text.
DbExpression resultExpression = null;
// If we are not converting a compiled query, or the referenced Entity-SQL ObjectQuery
// does not have parameters (and so no parameter references can be in the parsed tree)
// then the Entity-SQL can be parsed directly using the conversion command tree.
var objectParameters = inlineQuery.QueryState.Parameters;
if (!_funcletizer.IsCompiledQuery
|| objectParameters == null
|| objectParameters.Count == 0)
{
// Add parameters if they exist and we haven't yet encountered this inline query.
if (isNewInlineQuery && objectParameters != null)
{
// Copy the parameters into the aggregated parameter collection - this will result
// in an exception if any duplicate parameter names are encountered.
if (_parameters == null)
{
_parameters = new List<Tuple<ObjectParameter, QueryParameterExpression>>();
}
foreach (var prm in inlineQuery.QueryState.Parameters)
{
_parameters.Add(new Tuple<ObjectParameter, QueryParameterExpression>(prm.ShallowCopy(), null));
}
}
resultExpression = esqlState.Parse();
}
else
{
// We are converting a compiled query and parameters are present on the referenced ObjectQuery.
// The set of parameters available to a compiled query is fixed (so that adding/removing parameters
// to/from a referenced ObjectQuery does not invalidate the compiled query's execution plan), so the
// referenced ObjectQuery will be fully inlined by replacing each parameter reference with a
// DbConstantExpression containing the value of the referenced parameter.
resultExpression = esqlState.Parse();
resultExpression = ParameterReferenceRemover.RemoveParameterReferences(resultExpression, objectParameters);
}
return resultExpression;
}