Поигрался над прототипом для клиента, и переписал пару выборок с хранимок на Linq2db (SQL Server, Azure SQL).
Сиквел генерится просто чудестно, но есть некоторые вещи которых не хватает или я не нашел
Хотелось бы иметь возможнось вызывать всторенную фунцию ISNULL(SomeField, 0)
Не нашел возможности сделать BETWEEN, оно бы было как то нативней чем >= <=
Параметры дублируются, вот что получилось из всего двух переменных start и end
DECLARE @start1 DateTime2
SET @start1 = '2012-03-20'
DECLARE @end1 DateTime2
SET @end1 = '2015-03-20'
DECLARE @start2 DateTime2
SET @start2 = '2012-03-20'
DECLARE @end2 DateTime2
SET @end2 = '2015-03-20'
DECLARE @end3 DateTime2
SET @end3 = '2015-03-20'
SELECT
[s].[AccountName],
Sum(IIF([c].[RoutingCategory] = N'Resolved', [c].[PieceCount], 0)) as [c1],
Sum(IIF([c].[RoutingCategory] = N'Resolved', 0, [c].[PieceCount])) as [c2]
FROM
[dbo].[Counts] [c]
INNER JOIN [dbo].[Sessions] [s] ON [c].[Application] = [s].[Application] AND [c].[JobSessionID] = [s].[JobSessionID]
WHERE
NOT ([s].[AccountName] IS NULL OR Len([s].[AccountName]) = 0) AND
NOT ([s].[DepartmentName] IS NULL OR Len([s].[DepartmentName]) = 0) AND
NOT ([s].[MachineID] IS NULL OR Len([s].[MachineID]) = 0) AND
([s].[SessionStart] >= @start1 AND [s].[SessionStart] <= @end1 OR [s].[SessionStop] >= @start2 AND [s].[SessionStop] <= @end2) AND
[s].[SessionStart] <= @end3
GROUP BY
[s].[AccountName]
Уже как то говорил об этом, можна например при генерации держать список параметров и если название, тип и значение совпадают то переиспользовать.
D>Параметры дублируются, вот что получилось из всего двух переменных start и end D>Уже как то говорил об этом, можна например при генерации держать список параметров и если название, тип и значение совпадают то переиспользовать.
Генерируемый SQL кешируется. Соответственно совпадающие значения могут не совпадать при следующем запросе. Хотя, в принципе, это дело можно немного улучшить.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Danchik, Вы писали:
D>>Хотелось бы иметь возможнось вызывать всторенную фунцию ISNULL(SomeField, 0)
IT>Это делается с помощью оператора ??.
Посыпаю голову пеплом, но все равно, это не спасет при LEFT JOIN.
?? не поставишь на int поле.
D>>Не нашел возможности сделать BETWEEN, оно бы было как то нативней чем >= <=
IT>Обсуждалось тут http://rsdn.ru/forum/prj.rfd/5371102.hot
Почему бы сразу не встроить?
D>>Параметры дублируются, вот что получилось из всего двух переменных start и end D>>Уже как то говорил об этом, можна например при генерации держать список параметров и если название, тип и значение совпадают то переиспользовать.
IT>Генерируемый SQL кешируется. Соответственно совпадающие значения могут не совпадать при следующем запросе. Хотя, в принципе, это дело можно немного улучшить.
Приблизительно понял о чем речь и техническую загвоздку, но глаза все равно режет
Здравствуйте, Danchik, Вы писали:
D>Посыпаю голову пеплом, но все равно, это не спасет при LEFT JOIN. D>?? не поставишь на int поле.
Можно преобразовать к int?
Хотя согласен, имеет смысл добавить такую функцию. Кстати, это несложно сделать самостоятельно.
D>>>Не нашел возможности сделать BETWEEN, оно бы было как то нативней чем >= <= IT>>Обсуждалось тут http://rsdn.ru/forum/prj.rfd/5371102.hot
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Danchik, Вы писали:
D>>Посыпаю голову пеплом, но все равно, это не спасет при LEFT JOIN. D>>?? не поставишь на int поле.
IT>Можно преобразовать к int? IT>Хотя согласен, имеет смысл добавить такую функцию. Кстати, это несложно сделать самостоятельно.
[Sql.Expression("SqlServer", "ISNULL({0}, {1})", ServerSideOnly = true)]
public static T IsNull<T>(T? value, T defaultValue)
where T : struct
{
throw new NotImplementedException();
}
[Sql.Expression("SqlServer", "ISNULL({0}, {1})", ServerSideOnly = true)]
public static T IsNull<T>(T value, T defaultValue)
{
throw new NotImplementedException();
}
D>>Почему бы сразу не встроить?
IT>Там был задан вопрос о сигнатуре функции.
[Sql.Expression("SqlServer", "{0} BETWEEN {1} AND {2}", ServerSideOnly = false, Precedence = 1)]
public static bool Between<T>(T? value, T? low, T? high)
where T : struct, IComparable
{
if (!value.HasValue || !low.HasValue || !high.HasValue)
{
return false;
}
if (value.Value.CompareTo(low.Value) < 0)
return false;
if (value.Value.CompareTo(high.Value) > 0)
return false;
return true;
}
[Sql.Expression("SqlServer", "{0} BETWEEN {1} AND {2}", ServerSideOnly = false, Precedence = 1)]
public static bool Between<T>(T? value, T low, T high)
where T : struct, IComparable
{
if (!value.HasValue)
{
return false;
}
if (value.Value.CompareTo(low) < 0)
return false;
if (value.Value.CompareTo(high) > 0)
return false;
return true;
}
D>>Приблизительно понял о чем речь и техническую загвоздку, но глаза все равно режет
IT>Я надумал серьёзный рефакторинг linq провайдера, попробую заодно и решить этот вопрос.
Здравствуйте, Danchik, Вы писали:
D>Не нашел возможности сделать BETWEEN, оно бы было как то нативней чем >= <=
дарю:
[Sql.Expression("{0} BETWEEN {1} AND {2}", ServerSideOnly = true)]
public static bool Between<T>(T x, T low, T high) where T : IComparable<T>
{
// x >= low && x <= highreturn x.CompareTo(low) >= 0 && x.CompareTo(high) <= 0;
}
ИМХО в таком виде наиболее удобоваримо и можно добавить в linq2db
Здравствуйте, Danchik, Вы писали:
D>Совершенству нет пределов Это в который то раз?
На самом деле раньше это всё было допиливание существующего кода. Но накопился рад проблем, которые с текущим дизайном решить практически невозможно. Нужно полностью переписывать linq provider.
Не хотелось бы чтобы из-за внутренних проблем дизайна продукт начал тормозиться в развитии или вообще сдулся и тихо помер, как это практически произошло с Немерле.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Danchik, Вы писали:
D>>Совершенству нет пределов Это в который то раз?
IT>На самом деле раньше это всё было допиливание существующего кода. Но накопился рад проблем, которые с текущим дизайном решить практически невозможно. Нужно полностью переписывать linq provider.
IT>Не хотелось бы чтобы из-за внутренних проблем дизайна продукт начал тормозиться в развитии или вообще сдулся и тихо помер, как это практически произошло с Немерле.
Ну вот, хотелось бы обратить твое внимание на EF7, как у них сейчас организована загрузка Include — отдельные запросы наконец то посылают, но SQL опять же оставляет желать лучшего.
Здравствуйте, Danchik, Вы писали:
D>Ну вот, хотелось бы обратить твое внимание на EF7, как у них сейчас организована загрузка Include — отдельные запросы наконец то посылают, но SQL опять же оставляет желать лучшего.
В смысле отдельные запросы?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Danchik, Вы писали:
D>>Ну вот, хотелось бы обратить твое внимание на EF7, как у них сейчас организована загрузка Include — отдельные запросы наконец то посылают, но SQL опять же оставляет желать лучшего.
IT>В смысле отдельные запросы?
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Danchik, Вы писали:
D>>Они в суб запросы начинают включать главный как фильтр и накладывают на него DISTINCT
IT>DISTINCT — это сурово. даже на ПК не проверяют?
Здравствуйте, Danchik, Вы писали:
D>Ну вот, хотелось бы обратить твое внимание на EF7, как у них сейчас организована загрузка Include — отдельные запросы наконец то посылают, но SQL опять же оставляет желать лучшего.
А зачем это надо — отдельные запросы? Количество roundtrip до базы увеличивается, и возможно будет быстрее одним запросом получить кучу повторов, а затем извлечь из них сущности, чем делать отдельные запросы.
Здравствуйте, Слава, Вы писали:
С>А зачем это надо — отдельные запросы? Количество roundtrip до базы увеличивается, и возможно будет быстрее одним запросом получить кучу повторов, а затем извлечь из них сущности, чем делать отдельные запросы.
1. Серьёзно усложняется план запроса.
2. В разы увеличивается ширина запроса.
3. В разы увеличивается количество выгребаемых данных.
Одним запросом имеет смысл выгребать только связи один-к-одному.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Одним запросом имеет смысл выгребать только связи один-к-одному.
А есть ли какая-то возможность "прогреть кэш" linq2db? Я заметил, что при первом выполнении любого запроса, проходит немалое время, затем он выполняется моментально. Есть некоторое количество запросов, на которые, в зависимости от условий, накладываются ограничения where. То есть, кэшировать придется все комбинации фильтров. Можно ли как-то указать linq2db — "откомпилируй запрос, закээшируй, но не выполняй"?
Здравствуйте, Слава, Вы писали:
С>Здравствуйте, IT, Вы писали:
IT>>Одним запросом имеет смысл выгребать только связи один-к-одному.
С>А есть ли какая-то возможность "прогреть кэш" linq2db? Я заметил, что при первом выполнении любого запроса, проходит немалое время, затем он выполняется моментально. Есть некоторое количество запросов, на которые, в зависимости от условий, накладываются ограничения where. То есть, кэшировать придется все комбинации фильтров. Можно ли как-то указать linq2db — "откомпилируй запрос, закээшируй, но не выполняй"?
Я не уверен, надо на код смотреть, но если попробовать сделать для IQueryable ToString то запрос будет закеширован
Здравствуйте, Слава, Вы писали:
С>А есть ли какая-то возможность "прогреть кэш" linq2db? Я заметил, что при первом выполнении любого запроса, проходит немалое время, затем он выполняется моментально. Есть некоторое количество запросов, на которые, в зависимости от условий, накладываются ограничения where. То есть, кэшировать придется все комбинации фильтров. Можно ли как-то указать linq2db — "откомпилируй запрос, закээшируй, но не выполняй"?
Есть CompiledQuery, но там тоже запрос кешируется только в момент первого выполнения, т.к. нужен реальный DataContext от которого зависит генерация SQL.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Есть CompiledQuery, но там тоже запрос кешируется только в момент первого выполнения, т.к. нужен реальный DataContext от которого зависит генерация SQL.
Хотя для зависимых от условий запросов это не подойдёт.
Если нам не помогут, то мы тоже никого не пощадим.