предупреждение EF1000. Каков наилучший способ записи параметров в операторе «IN»? - PullRequest
0 голосов
/ 10 сентября 2018

EF Core 2.1 выдает предупреждения о внедрении SQL. Вот мой фрагмент кода, где это происходит

var query = await _ctx.Set<TABLE>()
                      .FromSql("Select * from TABLE where Artikelnummer IN (" + string.Join(',', artNum) + ")")
                      .AsNoTracking()
                      .Select(z => new
                      {
                        z.Artikelnummer,
                        z.Property
                      }).ToArrayAsync();

, где artNum (обозначает числа Артикеля) - это массив целых чисел, например, [1,22,34 и т. Д.].

Я не могу передать artNum в качестве параметров в FromSql, потому что будет одинарные кавычки и SQL выдает исключение.

Я могу переписать FromSql на

.Where(x => artNum.Contains(x.Artikelnummer))

Но у меня есть запросы, которые намного больше и сложнее, чем этот, поэтому LINQ to Entities не годится в этой ситуации. Так должно быть, вопрос в том, как переписать этот запрос, чтобы предупреждение не появлялось?

LINQ to Entities выполняется намного дольше, чем LINQ to SQL , поэтому это не подходящий способ решения моей проблемы.

Я исследовал, что конкатенация вызывает предупреждения, поэтому должно быть решение без конкатенации.

1 Ответ

0 голосов
/ 10 сентября 2018

Я не могу найти такого предупреждения в документации EF Core. И (что-то вроде) забавного в том, что транслятор запросов EF Core 2.1 не параметризует сгенерированные предложения SQL IN values. Что можно увидеть, если вы замените строку .FromSql вашего запроса на

.Where(x => artNum.Contains(x.Artikelnummer)

что, между прочим, является эквивалентом LINQ to Entities вашего запроса, который прекрасно переводит и выполняет, поэтому я не знаю, почему вы беспокоитесь о FromSql в данном конкретном случае.

Но в любом случае вы можете параметризовать запрос FromSql, включив {0}, {1} и т. Д. Внутри строки sql и передавая значения через params object[] parameters:

Как и для любого API, принимающего SQL, важно параметризовать любой пользовательский ввод для защиты от атаки SQL-инъекцией. Вы можете включить заполнители параметров в строку запроса SQL, а затем указать значения параметров в качестве дополнительных аргументов. Любые введенные вами значения параметров будут автоматически преобразованы в DbParameter

В вашем случае это может быть так:

var placeholders = string.Join(",", atrNum.Select((v, i) => "{" + i + "}"));
var values = atrNum.Cast<object>().ToArray();

.FromSql("Select * from TABLE where Artikelnummer IN (" + placeholders + ")", values)
...