示例#1
0
        public virtual RawSqlCommand Build(string sql, IReadOnlyList <object> parameters)
        {
            Check.NotEmpty(sql, nameof(sql));
            Check.NotNull(parameters, nameof(parameters));

            var relationalCommandBuilder = _relationalCommandBuilderFactory.Create();

            var substitutions = new string[parameters.Count];

            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

            var parameterValues = new Dictionary <string, object>();

            for (var i = 0; i < substitutions.Length; i++)
            {
                var parameterName = parameterNameGenerator.GenerateNext();

                substitutions[i] = _sqlGenerationHelper.GenerateParameterName(parameterName);

                relationalCommandBuilder.AddParameter(
                    parameterName,
                    substitutions[i]);

                parameterValues.Add(parameterName, parameters[i]);
            }

            // ReSharper disable once CoVariantArrayConversion
            sql = string.Format(sql, substitutions);

            return(new RawSqlCommand(
                       relationalCommandBuilder.Append(sql).Build(),
                       parameterValues));
        }
        public virtual IRelationalCommand Build(string sql, IReadOnlyList <object> parameters = null)
        {
            Check.NotEmpty(sql, nameof(sql));

            var relationalCommandBuilder = _relationalCommandBuilderFactory.Create();

            if (parameters != null)
            {
                var substitutions = new string[parameters.Count];

                var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

                for (var i = 0; i < substitutions.Length; i++)
                {
                    var parameterName = parameterNameGenerator.GenerateNext();

                    substitutions[i] = _sqlGenerationHelper.GenerateParameterName(parameterName);

                    relationalCommandBuilder.AddParameter(
                        substitutions[i],
                        parameters[i],
                        parameterName);
                }

                // ReSharper disable once CoVariantArrayConversion
                sql = string.Format(sql, substitutions);
            }

            return(relationalCommandBuilder.Append(sql).Build());
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual IEnumerable <ModificationCommandBatch> BatchCommands(IReadOnlyList <IUpdateEntry> entries)
        {
            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();
            var commands          = CreateModificationCommands(entries, parameterNameGenerator.GenerateNext);
            var sortedCommandSets = TopologicalSort(commands);

            // TODO: Enable batching of dependent commands by passing through the dependency graph
            foreach (var independentCommandSet in sortedCommandSets)
            {
                independentCommandSet.Sort(_modificationCommandComparer);

                var batch = _modificationCommandBatchFactory.Create();
                foreach (var modificationCommand in independentCommandSet)
                {
                    if (!batch.AddCommand(modificationCommand))
                    {
                        yield return(batch);

                        parameterNameGenerator.Reset();
                        batch = _modificationCommandBatchFactory.Create();
                        batch.AddCommand(modificationCommand);
                    }
                }

                yield return(batch);
            }
        }
示例#4
0
            public (SelectExpression selectExpression, bool canCache) Optimize(SelectExpression selectExpression, IReadOnlyDictionary <string, object> parametersValues)
            {
                var canCache = true;

                var inExpressionOptimized = new InExpressionValuesExpandingExpressionVisitor(
                    _sqlExpressionFactory, parametersValues).Visit(selectExpression);

                if (!ReferenceEquals(selectExpression, inExpressionOptimized))
                {
                    canCache = false;
                }

                var nullParametersOptimized = new ParameterNullabilityBasedSqlExpressionOptimizingExpressionVisitor(
                    _sqlExpressionFactory, _useRelationalNulls, parametersValues).Visit(inExpressionOptimized);

                var fromSqlParameterOptimized = new FromSqlParameterApplyingExpressionVisitor(
                    _sqlExpressionFactory,
                    _parameterNameGeneratorFactory.Create(),
                    parametersValues).Visit(nullParametersOptimized);

                if (!ReferenceEquals(nullParametersOptimized, fromSqlParameterOptimized))
                {
                    canCache = false;
                }

                return(selectExpression : (SelectExpression)fromSqlParameterOptimized, canCache);
            }
        public virtual IRelationalCommand Build(
            [NotNull] string sql,
            [CanBeNull] IReadOnlyList <object> parameters = null)
        {
            Check.NotEmpty(sql, nameof(sql));

            var builder = _commandBuilderFactory.Create();

            if (parameters != null)
            {
                var substitutions = new string[parameters.Count];

                var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

                for (var index = 0; index < substitutions.Length; index++)
                {
                    substitutions[index] =
                        _sqlGenerator.GenerateParameterName(
                            parameterNameGenerator.GenerateNext());

                    builder.AddParameter(
                        substitutions[index],
                        parameters[index]);
                }

                sql = string.Format(sql, substitutions);
            }

            return(builder.Append(sql).BuildRelationalCommand());
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual RawSqlCommand Build(string sql, IEnumerable <object> parameters)
        {
            Check.NotEmpty(sql, nameof(sql));
            Check.NotNull(parameters, nameof(parameters));

            var relationalCommandBuilder = _relationalCommandBuilderFactory.Create();

            var substitutions = new List <string>();

            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

            var parameterValues = new Dictionary <string, object>();

            foreach (var parameter in parameters)
            {
                var parameterName   = parameterNameGenerator.GenerateNext();
                var substitutedName = _sqlGenerationHelper.GenerateParameterName(parameterName);

                substitutions.Add(substitutedName);
                relationalCommandBuilder.AddParameter(parameterName, substitutedName);
                parameterValues.Add(parameterName, parameter);
            }

            // ReSharper disable once CoVariantArrayConversion
            sql = string.Format(sql, substitutions.ToArray());

            return(new RawSqlCommand(
                       relationalCommandBuilder.Append(sql).Build(),
                       parameterValues));
        }
            public SelectExpression Optimize(SelectExpression selectExpression, IReadOnlyDictionary <string, object> parametersValues)
            {
                var query = new InExpressionValuesExpandingExpressionVisitor(
                    _sqlExpressionFactory, parametersValues).Visit(selectExpression);

                query = new FromSqlParameterApplyingExpressionVisitor(
                    _sqlExpressionFactory,
                    _parameterNameGeneratorFactory.Create(),
                    parametersValues).Visit(query);

                return((SelectExpression)query);
            }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual IEnumerable <ModificationCommandBatch> BatchCommands(IReadOnlyList <IUpdateEntry> entries)
        {
            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();
            var commands          = CreateModificationCommands(entries, parameterNameGenerator.GenerateNext);
            var sortedCommandSets = TopologicalSort(commands);

            // TODO: Enable batching of dependent commands by passing through the dependency graph
            foreach (var independentCommandSet in sortedCommandSets)
            {
                independentCommandSet.Sort(_modificationCommandComparer);

                var batch = _modificationCommandBatchFactory.Create();
                foreach (var modificationCommand in independentCommandSet)
                {
                    Validate(modificationCommand);

                    if (!batch.AddCommand(modificationCommand))
                    {
                        if (batch.ModificationCommands.Count == 1 ||
                            batch.ModificationCommands.Count >= _minBatchSize)
                        {
                            yield return(batch);
                        }
                        else
                        {
                            foreach (var command in batch.ModificationCommands)
                            {
                                yield return(StartNewBatch(parameterNameGenerator, command));
                            }
                        }

                        batch = StartNewBatch(parameterNameGenerator, modificationCommand);
                    }
                }

                if (batch.ModificationCommands.Count == 1 ||
                    batch.ModificationCommands.Count >= _minBatchSize)
                {
                    yield return(batch);
                }
                else
                {
                    foreach (var command in batch.ModificationCommands)
                    {
                        yield return(StartNewBatch(parameterNameGenerator, command));
                    }
                }
            }
        }
    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual RawSqlCommand Build(string sql, IEnumerable <object> parameters)
    {
        var relationalCommandBuilder = _relationalCommandBuilderFactory.Create();

        var substitutions = new List <string>();

        var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

        var parameterValues = new Dictionary <string, object?>();

        foreach (var parameter in parameters)
        {
            if (parameter is DbParameter dbParameter)
            {
                if (string.IsNullOrEmpty(dbParameter.ParameterName))
                {
                    dbParameter.ParameterName = _sqlGenerationHelper.GenerateParameterName(parameterNameGenerator.GenerateNext());
                }

                substitutions.Add(_sqlGenerationHelper.GenerateParameterName(dbParameter.ParameterName));
                relationalCommandBuilder.AddRawParameter(dbParameter.ParameterName, dbParameter);
            }
            else
            {
                var parameterName   = parameterNameGenerator.GenerateNext();
                var substitutedName = _sqlGenerationHelper.GenerateParameterName(parameterName);

                substitutions.Add(substitutedName);
                var typeMapping = parameter == null
                        ? _typeMappingSource.GetMappingForValue(null)
                        : _typeMappingSource.GetMapping(parameter.GetType());

                var nullable = parameter == null || parameter.GetType().IsNullableType();

                relationalCommandBuilder.AddParameter(parameterName, substitutedName, typeMapping, nullable);
                parameterValues.Add(parameterName, parameter);
            }
        }

        // ReSharper disable once CoVariantArrayConversion
        sql = string.Format(sql, substitutions.ToArray());

        return(new RawSqlCommand(
                   relationalCommandBuilder.Append(sql).Build(),
                   parameterValues));
    }
示例#10
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual SelectExpression Expand(
            [NotNull] SelectExpression selectExpression, [NotNull] IReadOnlyDictionary <string, object> parameterValues, out bool canCache)
        {
            Check.NotNull(selectExpression, nameof(selectExpression));
            Check.NotNull(parameterValues, nameof(parameterValues));

            _visitedFromSqlExpressions.Clear();
            _parameterNameGenerator = _parameterNameGeneratorFactory.Create();
            _parametersValues       = parameterValues;
            _canCache = true;

            var result = (SelectExpression)Visit(selectExpression);

            canCache = _canCache;

            return(result);
        }
        protected virtual IEnumerable <ModificationCommand> CreateModificationCommands([NotNull] IReadOnlyList <IUpdateEntry> entries)
        {
            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

            // TODO: Handle multiple state entries that update the same row
            return(entries.Select(
                       e =>
            {
                var command = new ModificationCommand(
                    _annotationProvider.For(e.EntityType).TableName,
                    _annotationProvider.For(e.EntityType).Schema,
                    parameterNameGenerator,
                    _annotationProvider.For);

                command.AddEntry(e);
                return command;
            }));
        }
        private RelationalCommand CreateCommand(
            string sql,
            object[] parameters)
        {
            var builder = _relationalCommandBuilderFactory.Create();

            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();

            var substitutions = new string[parameters.Length];

            for (var index = 0; index < substitutions.Length; index++)
            {
                substitutions[index] = parameterNameGenerator.GenerateNext();
                builder.AddParameter(
                    substitutions[index],
                    parameters[index]);
            }

            builder.AppendLines(string.Format(sql, substitutions));

            return(builder.BuildRelationalCommand());
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual IEnumerable <ModificationCommandBatch> BatchCommands(IList <IUpdateEntry> entries)
        {
            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();
            var commands          = CreateModificationCommands(entries, parameterNameGenerator.GenerateNext);
            var sortedCommandSets = TopologicalSort(commands);

            // TODO: Enable batching of dependent commands by passing through the dependency graph
            foreach (var independentCommandSet in sortedCommandSets)
            {
                independentCommandSet.Sort(_modificationCommandComparer);

                var batch = _modificationCommandBatchFactory.Create();
                foreach (var modificationCommand in independentCommandSet)
                {
                    if (!batch.AddCommand(modificationCommand))
                    {
                        if (batch.ModificationCommands.Count == 1 ||
                            batch.ModificationCommands.Count >= _minBatchSize)
                        {
                            if (batch.ModificationCommands.Count > 1)
                            {
                                Dependencies.UpdateLogger.BatchReadyForExecution(
                                    batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count);
                            }

                            yield return(batch);
                        }
                        else
                        {
                            Dependencies.UpdateLogger.BatchSmallerThanMinBatchSize(
                                batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count, _minBatchSize);

                            foreach (var command in batch.ModificationCommands)
                            {
                                yield return(StartNewBatch(parameterNameGenerator, command));
                            }
                        }

                        batch = StartNewBatch(parameterNameGenerator, modificationCommand);
                    }
                }

                if (batch.ModificationCommands.Count == 1 ||
                    batch.ModificationCommands.Count >= _minBatchSize)
                {
                    if (batch.ModificationCommands.Count > 1)
                    {
                        Dependencies.UpdateLogger.BatchReadyForExecution(
                            batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count);
                    }

                    yield return(batch);
                }
                else
                {
                    Dependencies.UpdateLogger.BatchSmallerThanMinBatchSize(
                        batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count, _minBatchSize);

                    foreach (var command in batch.ModificationCommands)
                    {
                        yield return(StartNewBatch(parameterNameGenerator, command));
                    }
                }
            }
        }
示例#14
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual IEnumerable <ModificationCommandBatch> BatchCommands(
            IList <IUpdateEntry> entries,
            IUpdateAdapter updateAdapter)
        {
            var parameterNameGenerator = _parameterNameGeneratorFactory.Create();
            var commands          = CreateModificationCommands(entries, updateAdapter, parameterNameGenerator.GenerateNext);
            var sortedCommandSets = TopologicalSort(commands);

            foreach (var independentCommandSet in sortedCommandSets)
            {
                independentCommandSet.Sort(_modificationCommandComparer);

                var batch = _modificationCommandBatchFactory.Create();
                foreach (var modificationCommand in independentCommandSet)
                {
                    modificationCommand.AssertColumnsNotInitialized();
                    if (modificationCommand.EntityState == EntityState.Modified &&
                        !modificationCommand.ColumnModifications.Any(m => m.IsWrite))
                    {
                        continue;
                    }

                    if (!batch.AddCommand(modificationCommand))
                    {
                        if (batch.ModificationCommands.Count == 1 ||
                            batch.ModificationCommands.Count >= _minBatchSize)
                        {
                            if (batch.ModificationCommands.Count > 1)
                            {
                                Dependencies.UpdateLogger.BatchReadyForExecution(
                                    batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count);
                            }

                            yield return(batch);
                        }
                        else
                        {
                            Dependencies.UpdateLogger.BatchSmallerThanMinBatchSize(
                                batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count, _minBatchSize);

                            foreach (var command in batch.ModificationCommands)
                            {
                                yield return(StartNewBatch(parameterNameGenerator, command));
                            }
                        }

                        batch = StartNewBatch(parameterNameGenerator, modificationCommand);
                    }
                }

                if (batch.ModificationCommands.Count == 1 ||
                    batch.ModificationCommands.Count >= _minBatchSize)
                {
                    if (batch.ModificationCommands.Count > 1)
                    {
                        Dependencies.UpdateLogger.BatchReadyForExecution(
                            batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count);
                    }

                    yield return(batch);
                }
                else
                {
                    Dependencies.UpdateLogger.BatchSmallerThanMinBatchSize(
                        batch.ModificationCommands.SelectMany(c => c.Entries), batch.ModificationCommands.Count, _minBatchSize);

                    foreach (var command in batch.ModificationCommands)
                    {
                        yield return(StartNewBatch(parameterNameGenerator, command));
                    }
                }
            }
        }