private static ObjectParameterCollection MergeParameters(
            ObjectParameterCollection query1Params,
            ObjectParameterCollection query2Params)
        {
            if (query1Params == null && query2Params == null)
            {
                return((ObjectParameterCollection)null);
            }
            ObjectParameterCollection parameterCollection1;
            ObjectParameterCollection parameterCollection2;

            if (query1Params != null)
            {
                parameterCollection1 = ObjectParameterCollection.DeepCopy(query1Params);
                parameterCollection2 = query2Params;
            }
            else
            {
                parameterCollection1 = ObjectParameterCollection.DeepCopy(query2Params);
                parameterCollection2 = query1Params;
            }
            if (parameterCollection2 != null)
            {
                foreach (ObjectParameter objectParameter in parameterCollection2)
                {
                    parameterCollection1.Add(objectParameter.ShallowCopy());
                }
            }
            return(parameterCollection1);
        }
 public void Remove_throws_for_null_argument()
 {
     var objectParameterCollection = new ObjectParameterCollection(new ClrPerspective(new MetadataWorkspace()));
     Assert.Equal("item",
         Assert.Throws<ArgumentNullException>(
             () => objectParameterCollection.Remove(null)).ParamName);
 }
        internal static ObjectQueryState OfType(ObjectQueryState query, EdmType newType, Type clrOfType)
        {
            Debug.Assert(newType != null, "OfType cannot be null");
            Debug.Assert(Helper.IsEntityType(newType) || Helper.IsComplexType(newType), "OfType must be Entity or Complex type");

            string queryText = GetCommandText(query);

            // Build the new query string - "OFTYPE((<query>), [<type namespace>].[<type name>])"
            int queryLength = _ofTypeProlog.Length +
                              queryText.Length +
                              _ofTypeInfix.Length +
                              newType.NamespaceName.Length +
                              (newType.NamespaceName != string.Empty ? _ofTypeInfix2.Length : 0) +
                              newType.Name.Length +
                              _ofTypeEpilog.Length;

            StringBuilder builder = new StringBuilder(queryLength);

            builder.Append(_ofTypeProlog);
            builder.Append(queryText);
            builder.Append(_ofTypeInfix);
            if (newType.NamespaceName != string.Empty)
            {
                builder.Append(newType.NamespaceName);
                builder.Append(_ofTypeInfix2);
            }
            builder.Append(newType.Name);
            builder.Append(_ofTypeEpilog);

            // Create a new EntitySqlQueryImplementation that uses the new query as its command text.
            // Span is carried over, no adjustment is needed
            return(NewBuilderQuery(query, clrOfType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        /// <summary>
        /// Merges <see cref="ObjectParameter"/>s from two ObjectQuery arguments to SetOp builder methods (Except, Intersect, Union, UnionAll).
        /// A new <see cref="ObjectParameterCollection"/> is returned that contains copies of parameters from both <paramref name="query1Params"/> and <paramref name="query2Params"/>.
        /// </summary>
        /// <param name="query1Params">ObjectParameters from the first ObjectQuery argument (on which the query builder method was called)</param>
        /// <param name="query2Params">ObjectParameters from the second ObjectQuery argument (specified as an argument to the builder method)</param>
        /// <returns>A new ObjectParameterCollection containing copies of all parameters</returns>
        private static ObjectParameterCollection MergeParameters(ObjectParameterCollection query1Params, ObjectParameterCollection query2Params)
        {
            if (query1Params == null && query2Params == null)
            {
                return null;
            }

            ObjectParameterCollection mergedParams;
            ObjectParameterCollection sourceParams;
            if (query1Params != null)
            {
                mergedParams = ObjectParameterCollection.DeepCopy(query1Params);
                sourceParams = query2Params;
            }
            else
            {
                mergedParams = ObjectParameterCollection.DeepCopy(query2Params);
                sourceParams = query1Params;
            }

            if (sourceParams != null)
            {
                foreach (ObjectParameter sourceParam in sourceParams)
                {
                    mergedParams.Add(sourceParam.ShallowCopy());
                }
            }

            return mergedParams;
        }
示例#5
0
        private EntityCommand PrepareEntityCommand(
            ObjectContext context,
            ObjectParameterCollection parameterValues)
        {
            EntityCommandDefinition commandDefinition = (EntityCommandDefinition)this.CommandDefinition;
            EntityConnection        connection        = (EntityConnection)context.Connection;
            EntityCommand           entityCommand     = new EntityCommand(connection, commandDefinition, context.InterceptionContext, (EntityCommand.EntityDataReaderFactory)null);

            if (context.CommandTimeout.HasValue)
            {
                entityCommand.CommandTimeout = context.CommandTimeout.Value;
            }
            if (parameterValues != null)
            {
                foreach (ObjectParameter parameterValue in parameterValues)
                {
                    int index = entityCommand.Parameters.IndexOf(parameterValue.Name);
                    if (index != -1)
                    {
                        entityCommand.Parameters[index].Value = parameterValue.Value ?? (object)DBNull.Value;
                    }
                }
            }
            if (connection.CurrentTransaction != null)
            {
                entityCommand.Transaction = connection.CurrentTransaction;
            }
            return(entityCommand);
        }
示例#6
0
        private EntityCommand PrepareEntityCommand(ObjectContext context, ObjectParameterCollection parameterValues)
        {
            // create entity command (just do this to snarf store command)
            var commandDefinition = (EntityCommandDefinition)CommandDefinition;
            var entityCommand     = new EntityCommand(
                (EntityConnection)context.Connection, commandDefinition, context.InterceptionContext);

            // pass through parameters and timeout values
            if (context.CommandTimeout.HasValue)
            {
                entityCommand.CommandTimeout = context.CommandTimeout.Value;
            }

            if (parameterValues != null)
            {
                foreach (var parameter in parameterValues)
                {
                    var index = entityCommand.Parameters.IndexOf(parameter.Name);

                    if (index != -1)
                    {
                        entityCommand.Parameters[index].Value = parameter.Value ?? DBNull.Value;
                    }
                }
            }

            return(entityCommand);
        }
        /// <summary>
        /// Merges <see cref="ObjectParameter"/>s from two ObjectQuery arguments to SetOp builder methods (Except, Intersect, Union, UnionAll).
        /// A new <see cref="ObjectParameterCollection"/> is returned that contains copies of parameters from both <paramref name="query1Params"/> and <paramref name="query2Params"/>.
        /// </summary>
        /// <param name="query1Params">ObjectParameters from the first ObjectQuery argument (on which the query builder method was called)</param>
        /// <param name="query2Params">ObjectParameters from the second ObjectQuery argument (specified as an argument to the builder method)</param>
        /// <returns>A new ObjectParameterCollection containing copies of all parameters</returns>
        private static ObjectParameterCollection MergeParameters(ObjectParameterCollection query1Params, ObjectParameterCollection query2Params)
        {
            if (query1Params == null && query2Params == null)
            {
                return(null);
            }

            ObjectParameterCollection mergedParams;
            ObjectParameterCollection sourceParams;

            if (query1Params != null)
            {
                mergedParams = ObjectParameterCollection.DeepCopy(query1Params);
                sourceParams = query2Params;
            }
            else
            {
                mergedParams = ObjectParameterCollection.DeepCopy(query2Params);
                sourceParams = query1Params;
            }

            if (sourceParams != null)
            {
                foreach (ObjectParameter sourceParam in sourceParams)
                {
                    mergedParams.Add(sourceParam.ShallowCopy());
                }
            }

            return(mergedParams);
        }
示例#8
0
 protected ObjectQueryState(
     Type elementType,
     ObjectContext context,
     ObjectParameterCollection parameters,
     Span span)
 {
     this._elementType = elementType;
     this._context     = context;
     this._span        = span;
     this._parameters  = parameters;
 }
示例#9
0
 internal ObjectParameterCollection EnsureParameters()
 {
     if (this._parameters == null)
     {
         this._parameters = new ObjectParameterCollection(this.ObjectContext.Perspective);
         if (this._cachedPlan != null)
         {
             this._parameters.SetReadOnly(true);
         }
     }
     return(this._parameters);
 }
        public static void CopyTo(this ObjectParameterCollection parameters, DbCommand command, Func <string, string> fnGetParamName = null, IBatchRunner runner = null)
        {
            fnGetParamName = fnGetParamName ?? (paramName => paramName);
            runner         = runner ?? BatchExtensions.ResolveRunner();
            var nullValue = runner.DbNull;

            foreach (var objectParameter in parameters)
            {
                var parameter = command.CreateParameter();
                parameter.ParameterName = fnGetParamName(objectParameter.Name);
                parameter.Value         = objectParameter.Value ?? nullValue;
                command.Parameters.Add(parameter);
            }
        }
示例#11
0
        internal static ObjectQueryState Distinct(ObjectQueryState query)
        {
            // Build the new query string - "SET(<this query>)"
            string        queryText = GetCommandText(query);
            StringBuilder builder   = new StringBuilder(_distinctProlog.Length + queryText.Length + _distinctEpilog.Length);

            builder.Append(_distinctProlog);
            builder.Append(queryText);
            builder.Append(_distinctEpilog);

            // Span is carried over, no adjustment is needed

            return(NewBuilderQuery(query, query.ElementType, builder, query.Span, ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
示例#12
0
        /// <summary>
        ///   Constructs a new <see cref="ObjectQueryState"/> instance that uses the specified context and parameters collection.
        /// </summary>
        /// <param name="context">
        ///   The ObjectContext to which the implemented ObjectQuery belongs
        /// </param>
        protected ObjectQueryState(Type elementType, ObjectContext context, ObjectParameterCollection parameters, Span span)
        {
            // Validate the element type
            EntityUtil.CheckArgumentNull(elementType, "elementType");

            // Validate the context
            EntityUtil.CheckArgumentNull(context, "context");

            // Parameters and Span are specifically allowed to be null

            this._elementType = elementType;
            this._context     = context;
            this._span        = span;
            this._parameters  = parameters;
        }
示例#13
0
        // <summary>
        // Constructs a new <see cref="ObjectQueryState" /> instance that uses the specified context and parameters collection.
        // </summary>
        // <param name="context"> The ObjectContext to which the implemented ObjectQuery belongs </param>
        protected ObjectQueryState(Type elementType, ObjectContext context, ObjectParameterCollection parameters, Span span)
        {
            // Validate the element type
            DebugCheck.NotNull(elementType);

            // Validate the context
            DebugCheck.NotNull(context);

            // Parameters and Span are specifically allowed to be null

            _elementType = elementType;
            _context     = context;
            _span        = span;
            _parameters  = parameters;
        }
        private static ObjectParameterCollection MergeParameters(
            ObjectContext context,
            ObjectParameterCollection sourceQueryParams,
            ObjectParameter[] builderMethodParams)
        {
            if (sourceQueryParams == null && builderMethodParams.Length == 0)
            {
                return((ObjectParameterCollection)null);
            }
            ObjectParameterCollection parameterCollection = ObjectParameterCollection.DeepCopy(sourceQueryParams) ?? new ObjectParameterCollection(context.Perspective);

            foreach (ObjectParameter builderMethodParam in builderMethodParams)
            {
                parameterCollection.Add(builderMethodParam);
            }
            return(parameterCollection);
        }
示例#15
0
        internal virtual async Task <ObjectResult <TResultType> > ExecuteAsync <TResultType>(
            ObjectContext context,
            ObjectParameterCollection parameterValues,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            DbDataReader               storeReader    = (DbDataReader)null;
            BufferedDataReader         bufferedReader = (BufferedDataReader)null;
            ObjectResult <TResultType> objectResult;

            try
            {
                using (EntityCommand entityCommand = this.PrepareEntityCommand(context, parameterValues))
                    storeReader = await entityCommand.GetCommandDefinition().ExecuteStoreCommandsAsync(entityCommand, this.Streaming ? CommandBehavior.Default : CommandBehavior.SequentialAccess, cancellationToken).WithCurrentCulture <DbDataReader>();
                ShaperFactory <TResultType> shaperFactory = (ShaperFactory <TResultType>) this.ResultShaperFactory;
                Shaper <TResultType>        shaper;
                if (this.Streaming)
                {
                    shaper = shaperFactory.Create(storeReader, context, context.MetadataWorkspace, this.MergeOption, true, this.Streaming);
                }
                else
                {
                    StoreItemCollection storeItemCollection = (StoreItemCollection)context.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
                    DbProviderServices  providerServices    = DbConfiguration.DependencyResolver.GetService <DbProviderServices>((object)storeItemCollection.ProviderInvariantName);
                    bufferedReader = new BufferedDataReader(storeReader);
                    await bufferedReader.InitializeAsync(storeItemCollection.ProviderManifestToken, providerServices, shaperFactory.ColumnTypes, shaperFactory.NullableColumns, cancellationToken).WithCurrentCulture();

                    shaper = shaperFactory.Create((DbDataReader)bufferedReader, context, context.MetadataWorkspace, this.MergeOption, true, this.Streaming);
                }
                TypeUsage resultItemEdmType = this.ResultType.EdmType.BuiltInTypeKind != BuiltInTypeKind.CollectionType ? this.ResultType : ((CollectionType)this.ResultType.EdmType).TypeUsage;
                objectResult = new ObjectResult <TResultType>(shaper, this._singleEntitySet, resultItemEdmType);
            }
            catch (Exception ex)
            {
                if (this.Streaming && storeReader != null)
                {
                    storeReader.Dispose();
                }
                if (!this.Streaming && bufferedReader != null)
                {
                    bufferedReader.Dispose();
                }
                throw;
            }
            return(objectResult);
        }
示例#16
0
        private static ObjectQueryState NewBuilderQuery(ObjectQueryState sourceQuery, Type elementType, StringBuilder queryText, bool allowsLimit, Span newSpan, IEnumerable <ObjectParameter> enumerableParams)
        {
            ObjectParameterCollection queryParams = enumerableParams as ObjectParameterCollection;

            if (queryParams == null && enumerableParams != null)
            {
                queryParams = new ObjectParameterCollection(sourceQuery.ObjectContext.Perspective);
                foreach (ObjectParameter objectParam in enumerableParams)
                {
                    queryParams.Add(objectParam);
                }
            }

            EntitySqlQueryState newState = new EntitySqlQueryState(elementType, queryText.ToString(), allowsLimit, sourceQuery.ObjectContext, queryParams, newSpan);

            sourceQuery.ApplySettingsTo(newState);

            return(newState);
        }
示例#17
0
        internal virtual ObjectResult <TResultType> Execute <TResultType>(
            ObjectContext context,
            ObjectParameterCollection parameterValues)
        {
            DbDataReader       reader             = (DbDataReader)null;
            BufferedDataReader bufferedDataReader = (BufferedDataReader)null;

            try
            {
                using (EntityCommand entityCommand = this.PrepareEntityCommand(context, parameterValues))
                    reader = entityCommand.GetCommandDefinition().ExecuteStoreCommands(entityCommand, this.Streaming ? CommandBehavior.Default : CommandBehavior.SequentialAccess);
                ShaperFactory <TResultType> resultShaperFactory = (ShaperFactory <TResultType>) this.ResultShaperFactory;
                Shaper <TResultType>        shaper;
                if (this.Streaming)
                {
                    shaper = resultShaperFactory.Create(reader, context, context.MetadataWorkspace, this.MergeOption, true, this.Streaming);
                }
                else
                {
                    StoreItemCollection itemCollection = (StoreItemCollection)context.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
                    DbProviderServices  service        = DbConfiguration.DependencyResolver.GetService <DbProviderServices>((object)itemCollection.ProviderInvariantName);
                    bufferedDataReader = new BufferedDataReader(reader);
                    bufferedDataReader.Initialize(itemCollection.ProviderManifestToken, service, resultShaperFactory.ColumnTypes, resultShaperFactory.NullableColumns);
                    shaper = resultShaperFactory.Create((DbDataReader)bufferedDataReader, context, context.MetadataWorkspace, this.MergeOption, true, this.Streaming);
                }
                TypeUsage resultItemType = this.ResultType.EdmType.BuiltInTypeKind != BuiltInTypeKind.CollectionType ? this.ResultType : ((CollectionType)this.ResultType.EdmType).TypeUsage;
                return(new ObjectResult <TResultType>(shaper, this._singleEntitySet, resultItemType));
            }
            catch (Exception ex)
            {
                if (this.Streaming && reader != null)
                {
                    reader.Dispose();
                }
                if (!this.Streaming && bufferedDataReader != null)
                {
                    bufferedDataReader.Dispose();
                }
                throw;
            }
        }
        /// <summary>
        /// Merges <see cref="ObjectParameter"/>s from a source ObjectQuery with ObjectParameters specified as an argument to a builder method.
        /// A new <see cref="ObjectParameterCollection"/> is returned that contains copies of parameters from both <paramref name="sourceQueryParams"/> and <paramref name="builderMethodParams"/>.
        /// </summary>
        /// <param name="context">The <see cref="ObjectContext"/> to use when constructing the new parameter collection</param>
        /// <param name="sourceQueryParams">ObjectParameters from the ObjectQuery on which the query builder method was called</param>
        /// <param name="builderMethodParams">ObjectParameters that were specified as an argument to the builder method</param>
        /// <returns>A new ObjectParameterCollection containing copies of all parameters</returns>
        private static ObjectParameterCollection MergeParameters(ObjectContext context, ObjectParameterCollection sourceQueryParams, ObjectParameter[] builderMethodParams)
        {
            Debug.Assert(builderMethodParams != null, "params array argument should not be null");
            if (sourceQueryParams == null && builderMethodParams.Length == 0)
            {
                return null;
            }

            ObjectParameterCollection mergedParams = ObjectParameterCollection.DeepCopy(sourceQueryParams);
            if (mergedParams == null)
            {
                mergedParams = new ObjectParameterCollection(context.Perspective);
            }

            foreach (ObjectParameter builderParam in builderMethodParams)
            {
                mergedParams.Add(builderParam);
            }

            return mergedParams;
        }
示例#19
0
        /// <summary>
        /// Merges <see cref="ObjectParameter"/>s from a source ObjectQuery with ObjectParameters specified as an argument to a builder method.
        /// A new <see cref="ObjectParameterCollection"/> is returned that contains copies of parameters from both <paramref name="sourceQueryParams"/> and <paramref name="builderMethodParams"/>.
        /// </summary>
        /// <param name="context">The <see cref="ObjectContext"/> to use when constructing the new parameter collection</param>
        /// <param name="sourceQueryParams">ObjectParameters from the ObjectQuery on which the query builder method was called</param>
        /// <param name="builderMethodParams">ObjectParameters that were specified as an argument to the builder method</param>
        /// <returns>A new ObjectParameterCollection containing copies of all parameters</returns>
        private static ObjectParameterCollection MergeParameters(ObjectContext context, ObjectParameterCollection sourceQueryParams, ObjectParameter[] builderMethodParams)
        {
            Debug.Assert(builderMethodParams != null, "params array argument should not be null");
            if (sourceQueryParams == null && builderMethodParams.Length == 0)
            {
                return(null);
            }

            ObjectParameterCollection mergedParams = ObjectParameterCollection.DeepCopy(sourceQueryParams);

            if (mergedParams == null)
            {
                mergedParams = new ObjectParameterCollection(context.Perspective);
            }

            foreach (ObjectParameter builderParam in builderMethodParams)
            {
                mergedParams.Add(builderParam);
            }

            return(mergedParams);
        }
        // <summary>
        // Merges <see cref="ObjectParameter" />s from a source ObjectQuery with ObjectParameters specified as an argument to a builder method.
        // A new <see cref="ObjectParameterCollection" /> is returned that contains copies of parameters from both
        // <paramref
        //     name="sourceQueryParams" />
        // and <paramref name="builderMethodParams" />.
        // </summary>
        // <param name="context">
        // The <see cref="ObjectContext" /> to use when constructing the new parameter collection
        // </param>
        // <param name="sourceQueryParams"> ObjectParameters from the ObjectQuery on which the query builder method was called </param>
        // <param name="builderMethodParams"> ObjectParameters that were specified as an argument to the builder method </param>
        // <returns> A new ObjectParameterCollection containing copies of all parameters </returns>
        private static ObjectParameterCollection MergeParameters(
            ObjectContext context, ObjectParameterCollection sourceQueryParams, ObjectParameter[] builderMethodParams)
        {
            DebugCheck.NotNull(builderMethodParams);
            if (sourceQueryParams == null
                && builderMethodParams.Length == 0)
            {
                return null;
            }

            var mergedParams = ObjectParameterCollection.DeepCopy(sourceQueryParams);
            if (mergedParams == null)
            {
                mergedParams = new ObjectParameterCollection(context.Perspective);
            }

            foreach (var builderParam in builderMethodParams)
            {
                mergedParams.Add(builderParam);
            }

            return mergedParams;
        }
        // <summary>
        // Merges <see cref="ObjectParameter" />s from a source ObjectQuery with ObjectParameters specified as an argument to a builder method.
        // A new <see cref="ObjectParameterCollection" /> is returned that contains copies of parameters from both
        // <paramref
        //     name="sourceQueryParams" />
        // and <paramref name="builderMethodParams" />.
        // </summary>
        // <param name="context">
        // The <see cref="ObjectContext" /> to use when constructing the new parameter collection
        // </param>
        // <param name="sourceQueryParams"> ObjectParameters from the ObjectQuery on which the query builder method was called </param>
        // <param name="builderMethodParams"> ObjectParameters that were specified as an argument to the builder method </param>
        // <returns> A new ObjectParameterCollection containing copies of all parameters </returns>
        private static ObjectParameterCollection MergeParameters(
            ObjectContext context, ObjectParameterCollection sourceQueryParams, ObjectParameter[] builderMethodParams)
        {
            DebugCheck.NotNull(builderMethodParams);
            if (sourceQueryParams == null &&
                builderMethodParams.Length == 0)
            {
                return(null);
            }

            var mergedParams = ObjectParameterCollection.DeepCopy(sourceQueryParams);

            if (mergedParams == null)
            {
                mergedParams = new ObjectParameterCollection(context.Perspective);
            }

            foreach (var builderParam in builderMethodParams)
            {
                mergedParams.Add(builderParam);
            }

            return(mergedParams);
        }
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption?forMergeOption)
        {
            Debug.Assert(this.Span == null, "Include span specified on compiled LINQ-based ObjectQuery instead of within the expression tree?");
            Debug.Assert(this._cachedPlan == null, "Cached plan should not be set on compiled LINQ queries");

            // Metadata is required to generate the execution plan or to retrieve it from the cache.
            this.ObjectContext.EnsureMetadata();

            ObjectQueryExecutionPlan plan        = null;
            CompiledQueryCacheEntry  cacheEntry  = this._cacheEntry;
            bool useCSharpNullComparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;

            if (cacheEntry != null)
            {
                // The cache entry has already been retrieved, so compute the effective merge option with the following precedence:
                // 1. The merge option specified as the argument to Execute(MergeOption), and so to this method
                // 2. The merge option set using ObjectQuery.MergeOption
                // 3. The propagated merge option as recorded in the cache entry
                // 4. The global default merge option.
                MergeOption mergeOption = EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, cacheEntry.PropagatedMergeOption);

                // Ask for the corresponding execution plan
                plan = cacheEntry.GetExecutionPlan(mergeOption, useCSharpNullComparisonBehavior);
                if (plan == null)
                {
                    // Convert the LINQ expression to produce a command tree
                    ExpressionConverter converter       = this.CreateExpressionConverter();
                    DbExpression        queryExpression = converter.Convert();
                    ReadOnlyCollection <KeyValuePair <ObjectParameter, QueryParameterExpression> > parameters = converter.GetParameters();

                    // Prepare the execution plan using the command tree and the computed effective merge option
                    DbQueryCommandTree tree = DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, queryExpression);
                    plan = ObjectQueryExecutionPlan.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, converter.PropagatedSpan, parameters, converter.AliasGenerator);

                    // Update and retrieve the execution plan
                    plan = cacheEntry.SetExecutionPlan(plan, useCSharpNullComparisonBehavior);
                }
            }
            else
            {
                // This instance does not yet have a reference to a cache entry.
                // First, attempt to retrieve an existing cache entry.
                QueryCacheManager     cacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                CompiledQueryCacheKey cacheKey     = new CompiledQueryCacheKey(this._cacheToken);

                if (cacheManager.TryCacheLookup(cacheKey, out cacheEntry))
                {
                    // An entry was found in the cache, so compute the effective merge option based on its propagated merge option,
                    // and use the UseCSharpNullComparisonBehavior flag to retrieve the corresponding execution plan.
                    this._cacheEntry = cacheEntry;
                    MergeOption mergeOption = EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, cacheEntry.PropagatedMergeOption);
                    plan = cacheEntry.GetExecutionPlan(mergeOption, useCSharpNullComparisonBehavior);
                }

                // If no cache entry was found or if the cache entry did not contain the required execution plan, the plan is still null at this point.
                if (plan == null)
                {
                    // The execution plan needs to be produced, so create an appropriate expression converter and generate the query command tree.
                    ExpressionConverter converter       = this.CreateExpressionConverter();
                    DbExpression        queryExpression = converter.Convert();
                    ReadOnlyCollection <KeyValuePair <ObjectParameter, QueryParameterExpression> > parameters = converter.GetParameters();
                    DbQueryCommandTree tree = DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, queryExpression);

                    // If a cache entry for this compiled query's cache key was not successfully retrieved, then it must be created now.
                    // Note that this is only possible after converting the LINQ expression and discovering the propagated merge option,
                    // which is required in order to create the cache entry.
                    if (cacheEntry == null)
                    {
                        // Create the cache entry using this instance's cache token and the propagated merge option (which may be null)
                        cacheEntry = new CompiledQueryCacheEntry(cacheKey, converter.PropagatedMergeOption);

                        // Attempt to add the entry to the cache. If an entry was added in the meantime, use that entry instead.
                        QueryCacheEntry foundEntry;
                        if (cacheManager.TryLookupAndAdd(cacheEntry, out foundEntry))
                        {
                            cacheEntry = (CompiledQueryCacheEntry)foundEntry;
                        }

                        // We now have a cache entry, so hold onto it for future use.
                        this._cacheEntry = cacheEntry;
                    }

                    // Recompute the effective merge option in case a cache entry was just constructed above
                    MergeOption mergeOption = EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, cacheEntry.PropagatedMergeOption);

                    // Ask the (retrieved or constructed) cache entry for the corresponding execution plan.
                    plan = cacheEntry.GetExecutionPlan(mergeOption, useCSharpNullComparisonBehavior);
                    if (plan == null)
                    {
                        // The plan is not present, so prepare it now using the computed effective merge option
                        plan = ObjectQueryExecutionPlan.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, converter.PropagatedSpan, parameters, converter.AliasGenerator);

                        // Update the execution plan on the cache entry.
                        // If the execution plan was set in the meantime, SetExecutionPlan will return that value, otherwise it will return 'plan'.
                        plan = cacheEntry.SetExecutionPlan(plan, useCSharpNullComparisonBehavior);
                    }
                }
            }

            // Get parameters from the plan and set them.
            ObjectParameterCollection currentParams = this.EnsureParameters();

            if (plan.CompiledQueryParameters != null && plan.CompiledQueryParameters.Count > 0)
            {
                currentParams.SetReadOnly(false);
                currentParams.Clear();
                foreach (KeyValuePair <ObjectParameter, QueryParameterExpression> pair in plan.CompiledQueryParameters)
                {
                    // Parameters retrieved from the CompiledQueryParameters collection must be cloned before being added to the query.
                    // The cached plan is shared and when used in multithreaded scenarios failing to clone the parameter would result
                    // in the code below updating the values of shared parameter instances saved in the cached plan and used by all
                    // queries using that plan, regardless of the values they were actually invoked with, causing incorrect results
                    // when those queries were later executed.
                    //
                    ObjectParameter          convertedParam      = pair.Key.ShallowCopy();
                    QueryParameterExpression parameterExpression = pair.Value;
                    currentParams.Add(convertedParam);
                    if (parameterExpression != null)
                    {
                        convertedParam.Value = parameterExpression.EvaluateParameter(_parameterValues);
                    }
                }
            }
            currentParams.SetReadOnly(true);

            Debug.Assert(plan != null, "Failed to produce an execution plan?");
            return(plan);
        }
        internal static ObjectQueryState Distinct(ObjectQueryState query)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder("SET(\r\n".Length + commandText.Length + "\r\n)".Length);

            queryText.Append("SET(\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n)");
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, query.ElementType, queryText, query.Span, (IEnumerable <ObjectParameter>)ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
        internal static ObjectQueryState OfType(
            ObjectQueryState query,
            EdmType newType,
            Type clrOfType)
        {
            string        commandText = EntitySqlQueryBuilder.GetCommandText(query);
            StringBuilder queryText   = new StringBuilder("OFTYPE(\r\n(\r\n".Length + commandText.Length + "\r\n),\r\n[".Length + newType.NamespaceName.Length + (!string.IsNullOrEmpty(newType.NamespaceName) ? "].[".Length : 0) + newType.Name.Length + "]\r\n)".Length);

            queryText.Append("OFTYPE(\r\n(\r\n");
            queryText.Append(commandText);
            queryText.Append("\r\n),\r\n[");
            if (!string.IsNullOrEmpty(newType.NamespaceName))
            {
                queryText.Append(newType.NamespaceName);
                queryText.Append("].[");
            }
            queryText.Append(newType.Name);
            queryText.Append("]\r\n)");
            return(EntitySqlQueryBuilder.NewBuilderQuery(query, clrOfType, queryText, query.Span, (IEnumerable <ObjectParameter>)ObjectParameterCollection.DeepCopy(query.Parameters)));
        }
示例#25
0
        internal virtual ObjectResult <TResultType> Execute <TResultType>(ObjectContext context, ObjectParameterCollection parameterValues)
        {
            DbDataReader       storeReader    = null;
            BufferedDataReader bufferedReader = null;

            try
            {
                using (var entityCommand = PrepareEntityCommand(context, parameterValues))
                {
                    // acquire store reader
                    storeReader = entityCommand.GetCommandDefinition().ExecuteStoreCommands(
                        entityCommand,
                        Streaming
                            ? CommandBehavior.Default
                            : CommandBehavior.SequentialAccess);
                }

                var shaperFactory = (ShaperFactory <TResultType>)ResultShaperFactory;
                Shaper <TResultType> shaper;
                if (Streaming)
                {
                    shaper = shaperFactory.Create(
                        storeReader, context, context.MetadataWorkspace, MergeOption, true, useSpatialReader: true,
                        shouldReleaseConnection: Streaming);
                }
                else
                {
                    var storeItemCollection = (StoreItemCollection)context.MetadataWorkspace.GetItemCollection(DataSpace.SSpace);
                    var providerServices    = DbConfiguration.DependencyResolver.GetService <DbProviderServices>(storeItemCollection.StoreProviderInvariantName);

                    bufferedReader = new BufferedDataReader(storeReader);
                    bufferedReader.Initialize(storeItemCollection.StoreProviderManifestToken, providerServices);

                    shaper = shaperFactory.Create(
                        bufferedReader, context, context.MetadataWorkspace, MergeOption, true, useSpatialReader: false,
                        shouldReleaseConnection: Streaming);
                }

                // create materializer delegate
                TypeUsage resultItemEdmType;
                if (ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType)
                {
                    resultItemEdmType = ((CollectionType)ResultType.EdmType).TypeUsage;
                }
                else
                {
                    resultItemEdmType = ResultType;
                }

                return(new ObjectResult <TResultType>(shaper, _singleEntitySet, resultItemEdmType));
            }
            catch (Exception)
            {
                // Note: The ObjectResult is responsible for disposing the reader if creating
                // the enumerator fails.
                if (Streaming && storeReader != null)
                {
                    storeReader.Dispose();
                }

                if (!Streaming &&
                    bufferedReader != null)
                {
                    bufferedReader.Dispose();
                }
                throw;
            }
        }
            private ParameterReferenceRemover(ObjectParameterCollection availableParams)
            {
                Debug.Assert(availableParams != null, "Parameter collection cannot be null");

                objectParameters = availableParams;
            }
        internal override ObjectQueryExecutionPlan GetExecutionPlan(
            MergeOption?forMergeOption)
        {
            ObjectQueryExecutionPlan queryExecutionPlan1 = this._cachedPlan;

            if (queryExecutionPlan1 != null)
            {
                MergeOption?mergeOption = ObjectQueryState.GetMergeOption(forMergeOption, this.UserSpecifiedMergeOption);
                if (mergeOption.HasValue && mergeOption.Value != queryExecutionPlan1.MergeOption || (this._recompileRequired() || this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior != this._useCSharpNullComparisonBehavior))
                {
                    queryExecutionPlan1 = (ObjectQueryExecutionPlan)null;
                }
            }
            if (queryExecutionPlan1 == null)
            {
                this._recompileRequired = (Func <bool>)null;
                this.ResetParameters();
                ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                DbExpression        dbExpression        = expressionConverter.Convert();
                this._recompileRequired = expressionConverter.RecompileRequired;
                MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, expressionConverter.PropagatedMergeOption);
                this._useCSharpNullComparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;
                this._linqParameters = expressionConverter.GetParameters();
                if (this._linqParameters != null && this._linqParameters.Any <Tuple <ObjectParameter, QueryParameterExpression> >())
                {
                    ObjectParameterCollection parameterCollection = this.EnsureParameters();
                    parameterCollection.SetReadOnly(false);
                    foreach (Tuple <ObjectParameter, QueryParameterExpression> linqParameter in this._linqParameters)
                    {
                        ObjectParameter objectParameter = linqParameter.Item1;
                        parameterCollection.Add(objectParameter);
                    }
                    parameterCollection.SetReadOnly(true);
                }
                QueryCacheManager queryCacheManager = (QueryCacheManager)null;
                LinqQueryCacheKey key1 = (LinqQueryCacheKey)null;
                string            key2;
                if (this.PlanCachingEnabled && !this._recompileRequired() && ExpressionKeyGen.TryGenerateKey(dbExpression, out key2))
                {
                    key1 = new LinqQueryCacheKey(key2, this.Parameters == null ? 0 : this.Parameters.Count, this.Parameters == null ? (string)null : this.Parameters.GetCacheKey(), expressionConverter.PropagatedSpan == null ? (string)null : expressionConverter.PropagatedSpan.GetCacheKey(), mergeOption, this.EffectiveStreamingBehavior, this._useCSharpNullComparisonBehavior, this.ElementType);
                    queryCacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                    ObjectQueryExecutionPlan queryExecutionPlan2 = (ObjectQueryExecutionPlan)null;
                    if (queryCacheManager.TryCacheLookup <LinqQueryCacheKey, ObjectQueryExecutionPlan>(key1, out queryExecutionPlan2))
                    {
                        queryExecutionPlan1 = queryExecutionPlan2;
                    }
                }
                if (queryExecutionPlan1 == null)
                {
                    queryExecutionPlan1 = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, dbExpression, !this._useCSharpNullComparisonBehavior), this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, (IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> >)null, expressionConverter.AliasGenerator);
                    if (key1 != null)
                    {
                        QueryCacheEntry inQueryCacheEntry  = new QueryCacheEntry((QueryCacheKey)key1, (object)queryExecutionPlan1);
                        QueryCacheEntry outQueryCacheEntry = (QueryCacheEntry)null;
                        if (queryCacheManager.TryLookupAndAdd(inQueryCacheEntry, out outQueryCacheEntry))
                        {
                            queryExecutionPlan1 = (ObjectQueryExecutionPlan)outQueryCacheEntry.GetTarget();
                        }
                    }
                }
                this._cachedPlan = queryExecutionPlan1;
            }
            if (this._linqParameters != null)
            {
                foreach (Tuple <ObjectParameter, QueryParameterExpression> linqParameter in this._linqParameters)
                {
                    ObjectParameter          objectParameter     = linqParameter.Item1;
                    QueryParameterExpression parameterExpression = linqParameter.Item2;
                    if (parameterExpression != null)
                    {
                        objectParameter.Value = parameterExpression.EvaluateParameter((object[])null);
                    }
                }
            }
            return(queryExecutionPlan1);
        }
        private static ObjectQueryState NewBuilderQuery(ObjectQueryState sourceQuery, Type elementType, StringBuilder queryText, bool allowsLimit, Span newSpan, IEnumerable<ObjectParameter> enumerableParams)
        {
            ObjectParameterCollection queryParams = enumerableParams as ObjectParameterCollection;
            if (queryParams == null && enumerableParams != null)
            {
                queryParams = new ObjectParameterCollection(sourceQuery.ObjectContext.Perspective);
                foreach (ObjectParameter objectParam in enumerableParams)
                {
                    queryParams.Add(objectParam);
                }
            }

            EntitySqlQueryState newState = new EntitySqlQueryState(elementType, queryText.ToString(), allowsLimit, sourceQuery.ObjectContext, queryParams, newSpan);
            
            sourceQuery.ApplySettingsTo(newState);
            
            return newState;
        }
示例#29
0
            private ParameterReferenceRemover(ObjectParameterCollection availableParams)
            {
                DebugCheck.NotNull(availableParams);

                objectParameters = availableParams;
            }
示例#30
0
 internal static DbExpression RemoveParameterReferences(DbExpression expression, ObjectParameterCollection availableParameters)
 {
     var remover = new ParameterReferenceRemover(availableParameters);
     return remover.VisitExpression(expression);
 }
 public EntityFramework5DatabaseHelper(ObjectQuery objectQuery)
 {
     Connection = (objectQuery.Context.Connection as EntityConnection)?.StoreConnection;
     parameters = objectQuery.Parameters;
 }
        internal string ToTraceString(ObjectParameterCollection parameters = null)
        {
            var entityCommandDef = CommandDefinition as EntityCommandDefinition;

            if (entityCommandDef == null)
            {
                return(String.Empty);
            }

            var traceString = entityCommandDef.ToTraceString();

            if (parameters == null ||
                parameters.Count == 0)
            {
                return(traceString);
            }

            var command = CommandDefinition.CreateCommand();
            var sb      = new StringBuilder();

            sb.Append(traceString);
            sb.Append("\n\n/*\n");

            // append parameter information
            foreach (var objParam in parameters)
            {
                var index = command.Parameters.IndexOf(objParam.Name);

                if (index != -1)
                {
                    var dbParam = command.Parameters[index];
                    sb.Append(dbParam.DbType);
                }
                else
                {
                    Debug.Assert(
                        false,
                        "A parameter in the input ObjectParameterCollection does not have a match in the command definition's DbParameterCollection.");
                }

                sb.Append(" ");
                sb.Append(objParam.Name);
                sb.Append(" = ");

                var value = objParam.Value;
                var type  = (value != null) ? value.GetType() : null;

                switch (Type.GetTypeCode(type))
                {
                case TypeCode.Empty:
                case TypeCode.DBNull:
                    sb.Append("(null)");
                    break;

                case TypeCode.Char:
                    sb.Append("'");
                    sb.Append(value);
                    sb.Append("'");
                    break;

                case TypeCode.String:
                    sb.Append("\"");
                    sb.Append(value);
                    sb.Append("\"");
                    break;

                default:
                    sb.Append(value);
                    break;
                }

                sb.Append("\n");
            }

            sb.Append("*/\n");

            return(sb.ToString());
        }
        internal ObjectResult <TResultType> Execute <TResultType>(ObjectContext context, ObjectParameterCollection parameterValues)
        {
            DbDataReader storeReader = null;

            try
            {
                // create entity command (just do this to snarf store command)
                EntityCommandDefinition commandDefinition = (EntityCommandDefinition)this.CommandDefinition;
                EntityCommand           entityCommand     = new EntityCommand((EntityConnection)context.Connection, commandDefinition);

                // pass through parameters and timeout values
                if (context.CommandTimeout.HasValue)
                {
                    entityCommand.CommandTimeout = context.CommandTimeout.Value;
                }

                if (parameterValues != null)
                {
                    foreach (ObjectParameter parameter in parameterValues)
                    {
                        int index = entityCommand.Parameters.IndexOf(parameter.Name);

                        if (index != -1)
                        {
                            entityCommand.Parameters[index].Value = parameter.Value ?? DBNull.Value;
                        }
                    }
                }

                // acquire store reader
                storeReader = commandDefinition.ExecuteStoreCommands(entityCommand, CommandBehavior.Default);

                ShaperFactory <TResultType> shaperFactory = (ShaperFactory <TResultType>) this.ResultShaperFactory;
                Shaper <TResultType>        shaper        = shaperFactory.Create(storeReader, context, context.MetadataWorkspace, this.MergeOption, true);

                // create materializer delegate
                TypeUsage resultItemEdmType;

                if (ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType)
                {
                    resultItemEdmType = ((CollectionType)ResultType.EdmType).TypeUsage;
                }
                else
                {
                    resultItemEdmType = ResultType;
                }

                return(new ObjectResult <TResultType>(shaper, this._singleEntitySet, resultItemEdmType));
            }
            catch (Exception)
            {
                if (null != storeReader)
                {
                    // Note: The caller is responsible for disposing reader if creating
                    // the enumerator fails.
                    storeReader.Dispose();
                }
                throw;
            }
        }
        internal override ObjectQueryExecutionPlan GetExecutionPlan(MergeOption?forMergeOption)
        {
            Debug.Assert(this.Span == null, "Include span specified on compiled LINQ-based ObjectQuery instead of within the expression tree?");

            // If this query has already been prepared, its current execution plan may no longer be valid.
            ObjectQueryExecutionPlan plan = this._cachedPlan;

            if (plan != null)
            {
                // Was a merge option specified in the call to Execute(MergeOption) or set via ObjectQuery.MergeOption?
                MergeOption?explicitMergeOption = GetMergeOption(forMergeOption, this.UserSpecifiedMergeOption);

                // If a merge option was explicitly specified, and it does not match the plan's merge option, then the plan is no longer valid.
                // If the context flag UseCSharpNullComparisonBehavior was modified, then the plan is no longer valid.
                if ((explicitMergeOption.HasValue &&
                     explicitMergeOption.Value != plan.MergeOption) ||
                    this._recompileRequired() ||
                    this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior != this._useCSharpNullComparisonBehavior)
                {
                    plan = null;
                }
            }

            // The plan may have been invalidated above, or this query may never have been prepared.
            if (plan == null)
            {
                // Metadata is required to generate the execution plan.
                this.ObjectContext.EnsureMetadata();

                // Reset internal state
                this._recompileRequired = null;
                this.ResetParameters();

                // Translate LINQ expression to a DbExpression
                ExpressionConverter converter       = this.CreateExpressionConverter();
                DbExpression        queryExpression = converter.Convert();

                // This delegate tells us when a part of the expression tree has changed requiring a recompile.
                this._recompileRequired = converter.RecompileRequired;

                // Determine the merge option, with the following precedence:
                // 1. A merge option was specified explicitly as the argument to Execute(MergeOption).
                // 2. The user has set the MergeOption property on the ObjectQuery instance.
                // 3. A merge option has been extracted from the 'root' query and propagated to the root of the expression tree.
                // 4. The global default merge option.
                MergeOption mergeOption = EnsureMergeOption(forMergeOption,
                                                            this.UserSpecifiedMergeOption,
                                                            converter.PropagatedMergeOption);

                this._useCSharpNullComparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;

                // If parameters were aggregated from referenced (non-LINQ) ObjectQuery instances then add them to the parameters collection
                _linqParameters = converter.GetParameters();
                if (_linqParameters != null && _linqParameters.Count > 0)
                {
                    ObjectParameterCollection currentParams = this.EnsureParameters();
                    currentParams.SetReadOnly(false);
                    foreach (KeyValuePair <ObjectParameter, QueryParameterExpression> pair in _linqParameters)
                    {
                        // Note that it is safe to add the parameter directly only
                        // because parameters are cloned before they are added to the
                        // converter's parameter collection, or they came from this
                        // instance's parameter collection in the first place.
                        ObjectParameter convertedParam = pair.Key;
                        currentParams.Add(convertedParam);
                    }
                    currentParams.SetReadOnly(true);
                }

                // Try retrieving the execution plan from the global query cache (if plan caching is enabled).
                System.Data.Common.QueryCache.QueryCacheManager cacheManager = null;
                System.Data.Common.QueryCache.LinqQueryCacheKey cacheKey     = null;
                if (this.PlanCachingEnabled && !this._recompileRequired())
                {
                    // Create a new cache key that reflects the current state of the Parameters collection
                    // and the Span object (if any), and uses the specified merge option.
                    string expressionKey;
                    if (ExpressionKeyGen.TryGenerateKey(queryExpression, out expressionKey))
                    {
                        cacheKey = new System.Data.Common.QueryCache.LinqQueryCacheKey(
                            expressionKey,
                            (null == this.Parameters ? 0 : this.Parameters.Count),
                            (null == this.Parameters ? null : this.Parameters.GetCacheKey()),
                            (null == converter.PropagatedSpan ? null : converter.PropagatedSpan.GetCacheKey()),
                            mergeOption,
                            this._useCSharpNullComparisonBehavior,
                            this.ElementType);

                        cacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                        ObjectQueryExecutionPlan executionPlan = null;
                        if (cacheManager.TryCacheLookup(cacheKey, out executionPlan))
                        {
                            plan = executionPlan;
                        }
                    }
                }

                // If execution plan wasn't retrieved from the cache, build a new one and cache it.
                if (plan == null)
                {
                    DbQueryCommandTree tree = DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, queryExpression);
                    plan = ObjectQueryExecutionPlan.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, converter.PropagatedSpan, null, converter.AliasGenerator);

                    // If caching is enabled then update the cache now.
                    // Note: the logic is the same as in EntitySqlQueryState.
                    if (cacheKey != null)
                    {
                        var             newEntry   = new QueryCacheEntry(cacheKey, plan);
                        QueryCacheEntry foundEntry = null;
                        if (cacheManager.TryLookupAndAdd(newEntry, out foundEntry))
                        {
                            // If TryLookupAndAdd returns 'true' then the entry was already present in the cache when the attempt to add was made.
                            // In this case the existing execution plan should be used.
                            plan = (ObjectQueryExecutionPlan)foundEntry.GetTarget();
                        }
                    }
                }

                // Remember the current plan in the local cache, so that we don't have to recalc the key and look into the global cache
                // if the same instance of query gets executed more than once.
                this._cachedPlan = plan;
            }

            // Evaluate parameter values for the query.
            if (_linqParameters != null)
            {
                foreach (KeyValuePair <ObjectParameter, QueryParameterExpression> pair in _linqParameters)
                {
                    ObjectParameter          parameter           = pair.Key;
                    QueryParameterExpression parameterExpression = pair.Value;
                    if (null != parameterExpression)
                    {
                        parameter.Value = parameterExpression.EvaluateParameter(null);
                    }
                }
            }

            return(plan);
        }
        internal virtual async Task <ObjectResult <TResultType> > ExecuteAsync <TResultType>(
            ObjectContext context, ObjectParameterCollection parameterValues,
            CancellationToken cancellationToken)
        {
            DbDataReader storeReader = null;

            try
            {
                // create entity command (just do this to snarf store command)
                var commandDefinition = (EntityCommandDefinition)CommandDefinition;
                var entityCommand     = new EntityCommand((EntityConnection)context.Connection, commandDefinition);

                // pass through parameters and timeout values
                if (context.CommandTimeout.HasValue)
                {
                    entityCommand.CommandTimeout = context.CommandTimeout.Value;
                }

                if (parameterValues != null)
                {
                    foreach (var parameter in parameterValues)
                    {
                        var index = entityCommand.Parameters.IndexOf(parameter.Name);

                        if (index != -1)
                        {
                            entityCommand.Parameters[index].Value = parameter.Value ?? DBNull.Value;
                        }
                    }
                }

                // acquire store reader
                storeReader = await
                              commandDefinition.ExecuteStoreCommandsAsync(entityCommand, CommandBehavior.Default, cancellationToken).
                              ConfigureAwait(continueOnCapturedContext: false);

                var shaperFactory = (ShaperFactory <TResultType>)ResultShaperFactory;
                var shaper        = shaperFactory.Create(storeReader, context, context.MetadataWorkspace, MergeOption, true);

                // create materializer delegate
                TypeUsage resultItemEdmType;

                if (ResultType.EdmType.BuiltInTypeKind
                    == BuiltInTypeKind.CollectionType)
                {
                    resultItemEdmType = ((CollectionType)ResultType.EdmType).TypeUsage;
                }
                else
                {
                    resultItemEdmType = ResultType;
                }

                return(new ObjectResult <TResultType>(shaper, _singleEntitySet, resultItemEdmType));
            }
            catch (Exception)
            {
                if (null != storeReader)
                {
                    // Note: The caller is responsible for disposing reader if creating
                    // the enumerator fails.
                    storeReader.Dispose();
                }
                throw;
            }
        }
示例#36
0
        internal override ObjectQueryExecutionPlan GetExecutionPlan(
            MergeOption?forMergeOption)
        {
            ObjectQueryExecutionPlan queryExecutionPlan      = (ObjectQueryExecutionPlan)null;
            CompiledQueryCacheEntry  compiledQueryCacheEntry = this._cacheEntry;
            bool comparisonBehavior = this.ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior;

            if (compiledQueryCacheEntry != null)
            {
                MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                if (queryExecutionPlan == null)
                {
                    ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                    DbExpression        query = expressionConverter.Convert();
                    IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > parameters = expressionConverter.GetParameters();
                    ObjectQueryExecutionPlan newPlan = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, query, !comparisonBehavior), this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, parameters, expressionConverter.AliasGenerator);
                    queryExecutionPlan = compiledQueryCacheEntry.SetExecutionPlan(newPlan, comparisonBehavior);
                }
            }
            else
            {
                QueryCacheManager     queryCacheManager = this.ObjectContext.MetadataWorkspace.GetQueryCacheManager();
                CompiledQueryCacheKey key = new CompiledQueryCacheKey(this._cacheToken);
                if (queryCacheManager.TryCacheLookup <CompiledQueryCacheKey, CompiledQueryCacheEntry>(key, out compiledQueryCacheEntry))
                {
                    this._cacheEntry = compiledQueryCacheEntry;
                    MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                    queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                }
                if (queryExecutionPlan == null)
                {
                    ExpressionConverter expressionConverter = this.CreateExpressionConverter();
                    DbExpression        query = expressionConverter.Convert();
                    IEnumerable <Tuple <ObjectParameter, QueryParameterExpression> > parameters = expressionConverter.GetParameters();
                    DbQueryCommandTree tree = DbQueryCommandTree.FromValidExpression(this.ObjectContext.MetadataWorkspace, DataSpace.CSpace, query, !comparisonBehavior);
                    if (compiledQueryCacheEntry == null)
                    {
                        compiledQueryCacheEntry = new CompiledQueryCacheEntry((QueryCacheKey)key, expressionConverter.PropagatedMergeOption);
                        QueryCacheEntry outQueryCacheEntry;
                        if (queryCacheManager.TryLookupAndAdd((QueryCacheEntry)compiledQueryCacheEntry, out outQueryCacheEntry))
                        {
                            compiledQueryCacheEntry = (CompiledQueryCacheEntry)outQueryCacheEntry;
                        }
                        this._cacheEntry = compiledQueryCacheEntry;
                    }
                    MergeOption mergeOption = ObjectQueryState.EnsureMergeOption(forMergeOption, this.UserSpecifiedMergeOption, compiledQueryCacheEntry.PropagatedMergeOption);
                    queryExecutionPlan = compiledQueryCacheEntry.GetExecutionPlan(mergeOption, comparisonBehavior);
                    if (queryExecutionPlan == null)
                    {
                        ObjectQueryExecutionPlan newPlan = this._objectQueryExecutionPlanFactory.Prepare(this.ObjectContext, tree, this.ElementType, mergeOption, this.EffectiveStreamingBehavior, expressionConverter.PropagatedSpan, parameters, expressionConverter.AliasGenerator);
                        queryExecutionPlan = compiledQueryCacheEntry.SetExecutionPlan(newPlan, comparisonBehavior);
                    }
                }
            }
            ObjectParameterCollection parameterCollection = this.EnsureParameters();

            if (queryExecutionPlan.CompiledQueryParameters != null && queryExecutionPlan.CompiledQueryParameters.Any <Tuple <ObjectParameter, QueryParameterExpression> >())
            {
                parameterCollection.SetReadOnly(false);
                parameterCollection.Clear();
                foreach (Tuple <ObjectParameter, QueryParameterExpression> compiledQueryParameter in queryExecutionPlan.CompiledQueryParameters)
                {
                    ObjectParameter          objectParameter     = compiledQueryParameter.Item1.ShallowCopy();
                    QueryParameterExpression parameterExpression = compiledQueryParameter.Item2;
                    parameterCollection.Add(objectParameter);
                    if (parameterExpression != null)
                    {
                        objectParameter.Value = parameterExpression.EvaluateParameter(this._parameterValues);
                    }
                }
            }
            parameterCollection.SetReadOnly(true);
            return(queryExecutionPlan);
        }