Ejemplo n.º 1
0
        private static void RuntimeAddDynamicParameters(
            DbCommand dbCommand,
            StringBuilder stringBuilder,
            string fragment,
            Func <IEnumerable> values,
            string name,
            IQueryFormattingProvider queryFormattingProvider,
            DbType?dbType,
            Func <object, object> conversion)
        {
            DbParameter parameter;
            string      formattedName;
            IEnumerator enumerator     = default;
            var         index          = 0;
            var         addedParameter = false;
            var         foundNull      = false;

            try
            {
                enumerator = values().GetEnumerator();

                var insertPoint = stringBuilder.Length;

                stringBuilder.Append(fragment);

                if (enumerator.MoveNext())
                {
                    if (enumerator.Current == null)
                    {
                        foundNull = true;
                    }
                    else
                    {
                        if (!addedParameter)
                        {
                            stringBuilder.Append(" IN (");
                        }

                        addedParameter = true;
                        formattedName  = queryFormattingProvider.FormatParameterName($"{name}_{index++}");
                        stringBuilder.Append(formattedName);
                        parameter = dbCommand.CreateParameter();
                        parameter.ParameterName = formattedName;

                        if (conversion != null)
                        {
                            parameter.Value = conversion(enumerator.Current);
                        }
                        else
                        {
                            parameter.Value = enumerator.Current;
                        }

                        if (dbType.HasValue)
                        {
                            parameter.DbType = dbType.Value;
                        }

                        dbCommand.Parameters.Add(parameter);
                    }

                    while (enumerator.MoveNext())
                    {
                        if (enumerator.Current == null)
                        {
                            foundNull = true;
                        }
                        else
                        {
                            formattedName = queryFormattingProvider.FormatParameterName($"{name}_{index++}");

                            if (!addedParameter)
                            {
                                stringBuilder.Append($" IN ({formattedName}");
                            }
                            else
                            {
                                stringBuilder.Append($", {formattedName}");
                            }

                            addedParameter          = true;
                            parameter               = dbCommand.CreateParameter();
                            parameter.ParameterName = formattedName;

                            if (conversion != null)
                            {
                                parameter.Value = conversion(enumerator.Current);
                            }
                            else
                            {
                                parameter.Value = enumerator.Current;
                            }

                            if (dbType.HasValue)
                            {
                                parameter.DbType = dbType.Value;
                            }

                            dbCommand.Parameters.Add(parameter);
                        }
                    }
                }

                if (!addedParameter)
                {
                    if (!foundNull)
                    {
                        stringBuilder.Append(" IN (NULL)");
                    }
                    else
                    {
                        stringBuilder.Append(" IS NULL");
                    }
                }
                else
                {
                    stringBuilder.Append(")");

                    if (foundNull)
                    {
                        stringBuilder.Insert(insertPoint, "(");
                        stringBuilder.Append(" OR ");
                        stringBuilder.Append(fragment);
                        stringBuilder.Append(" IS NULL");
                        stringBuilder.Append(")");
                    }
                }
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException("Error while applying parameters to the query", exception);
            }
            finally
            {
                if (enumerator is IDisposable disposable)
                {
                    disposable.Dispose();
                }
            }
        }
Ejemplo n.º 2
0
        public void AddParameter(SqlParameterExpression node)
        {
            var hash = ExpressionEqualityComparer.Instance.GetHashCode(node);

            if (parameterCache.TryGetValue(hash, out var cachedIndex))
            {
                Append(queryFormattingProvider.FormatParameterName($"p{cachedIndex}"));

                return;
            }

            var parameterName = queryFormattingProvider.FormatParameterName($"p{parameterIndex}");

            parameterCache[hash] = parameterIndex;
            parameterIndex++;

            Append(parameterName);

            EmitSql();

            var typeMapping = node.TypeMapping ?? typeMappingProvider.FindMapping(node.Type);

            if (typeMapping is null)
            {
                throw new InvalidOperationException($"Could not find a type mapping for a parameter value: {node}");
            }

            Expression value = node;

            if (typeMapping.SourceConversion is LambdaExpression conversion)
            {
                var expansion = value;

                var inputType = conversion.Parameters.Single().Type;

                if (expansion.Type != inputType)
                {
                    if (expansion.Type == typeMapping.TargetConversion.Parameters.Single().Type)
                    {
                        expansion = typeMapping.TargetConversion.ExpandParameters(expansion);
                    }
                    else
                    {
                        expansion = Expression.Convert(expansion, inputType);
                    }
                }

                value = conversion.ExpandParameters(expansion);
            }

            if (node.Type.IsNullableType() || !node.Type.GetTypeInfo().IsValueType)
            {
                value
                    = Expression.Condition(
                          Expression.Equal(node, Expression.Constant(null)),
                          Expression.Constant(null),
                          Expression.Convert(value, typeof(object)));
            }

            var expression
                = Expression.Call(
                      GetType().GetMethod(nameof(RuntimeAddParameter), BindingFlags.NonPublic | BindingFlags.Static),
                      dbCommandVariable,
                      Expression.Constant(parameterName),
                      Expression.Constant(typeMapping.DbType, typeof(DbType?)),
                      Expression.Lambda(typeof(Func <object>), Expression.Convert(value, typeof(object))));

            blockExpressions.Add(expression);
            dbParameterExpressions.Add(expression);
        }