FromSql приводит к ошибке, в то время как запрос работает в pgAdmin - PullRequest
0 голосов
/ 22 марта 2019

Чтобы заменить следующий запрос, который генерирует предложение IN, на 100+ элементов внутри и занимает 8,4 секунды:

List<AnalysisModel> analyses = AppDbContext.Analysis.Where(m => Id.Contains(m.TestId) & phasesAll.Contains(m.PhaseId)).AsNoTracking().ToList();

Я использую ручной запрос:

string analysisQuery = $"SELECT id, time, compound, reagent, product, phase, conc, test_id FROM public.analysis INNER JOIN (VALUES {stringHelper.WrapGuidToString(Id, GuidWrapper) } ) testid_val (v) ON (test_id = v) INNER JOIN (VALUES {stringHelper.WrapIntToString(phasesAll, IntWrapper) }) phase_val (p)ON (phase = p)";
List<AnalysisModel> analyses = AppDbContext.Analysis.FromSql(analysisQuery).AsNoTracking().ToList();

Если я выполняю запрос, сгенерированный в analysisQuery в pgAdmin, он выполняется и предоставляет ту же таблицу, что и первое выражение (в 0,9 с). Однако, когда я выполняю через FromSql, я получаю следующую ошибку:

System.FormatException: индекс (на основе нуля) должен быть больше или равно нулю и меньше размера списка аргументов. '

Есть предложения, почему FromSql здесь не работает правильно?

stringHelper.WrapGuidToString() и stringHelper.WrapIntToString() переносит Guid и строку в соответствующий формат, например ({Guid1}), ({Guid2}) и (1), (2) для Guid и Int соответственно. Запрос, сгенерированный этим методом, можно без проблем выполнить в pgAdmin:

public string WrapIntToString(List<int> input, WrapModel wrapper)
{
 List<string> prep = new List<string>();
 input.ForEach(m => prep.Add(wrapper.LeftWrapper + m.ToString() + wrapper.RightWrapper));
 return string.Join(wrapper.Separator, prep);
}

WrapGuidToString код:

public string WrapGuidToString(List<Guid> input, WrapModel wrapper)
{
 List<string> prep = new List<string>();
 input.ForEach(m => prep.Add(wrapper.LeftWrapper + m.ToString() + wrapper.RightWrapper));
 return string.Join(wrapper.Separator, prep);
}

Где wrapper равно

private WrapModel GuidWrapper => new WrapModel()
{
 LeftWrapper = "('{",
 RightWrapper = "}'::uuid)",
 Separator = ","
};

1 Ответ

0 голосов
/ 26 марта 2019

У меня есть ваша проблема:

wrapper.LeftWrapper + m.ToString() + wrapper.RightWrapper

Кажется, вы создали строковый формат {yourStringValueHere}, поэтому вы получили эту ошибку Zero index

String.Format("{0}{1}{2}","Value1","Value2","Value3")

Это должновыглядит так.

Этот m.ToString() с вашей оберткой неправильный вместо integer, за которым следует значение

Посмотрите на содержимое ваших WrapGuidToString или WrapIntToString если оно в правильном формате.Это ваша главная проблема здесь.

...