Чтобы заменить следующий запрос, который генерирует предложение 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 = ","
};