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(); } } }
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); }