Информация об изменениях

Сообщение Re: [linq2db bug] Исключение в запросе с OUTER APPLY от 07.08.2018 15:27

Изменено 07.08.2018 15:43 Danchik

Re: [linq2db bug] Исключение в запросе с OUTER APPLY
Здравствуйте, Петрухин Эдуард, Вы писали:

[Skip]

ПЭ>Для меня больше важен вариант с

ПЭ>
ПЭ>from book in books
ПЭ>where book.AuthorId == author.Id
ПЭ>select new
ПЭ>{
ПЭ>    Count = Sql.Ext.Count(book.Id).ToValue()
ПЭ>}
ПЭ>

ПЭ>потому что на практике надо считать по подзапросу не один агрегат, а несколько.

Проанализировал я — дело непростое. То как вы записали выражение, это еще парсать и парсать.
Я записал его вот так, и все корректно. И блоками тоже можно достраивать.

var aggregates = from book in db.GetTable<Book>()
    select new
    {
        book.AuthorId,
        RN = Sql.Ext.RowNumber().Over().OrderBy(book.AuthorId).ToValue(),

        BooksCount = Sql.Ext.Count(book.Id).Over().PartitionBy(book.AuthorId).ToValue(),
        Count2 = Sql.Ext.Count(book.Title).Over().PartitionBy(book.AuthorId).ToValue(),
    };

aggregates = aggregates.Where(a => a.RN == 1);

var query = from author in db.GetTable<Author>()
    from a in aggregates.InnerJoin(a => a.AuthorId == author.Id)
    where a.BooksCount > 42
    select new
    {
        author.Name,
        BooksCount = a.BooksCount
    };


Если дадите сценарий более четко с типами запросов что будут, можно и солюшин придумать.
Re: [linq2db bug] Исключение в запросе с OUTER APPLY
Здравствуйте, Петрухин Эдуард, Вы писали:

[Skip]

ПЭ>Для меня больше важен вариант с

ПЭ>
ПЭ>from book in books
ПЭ>where book.AuthorId == author.Id
ПЭ>select new
ПЭ>{
ПЭ>    Count = Sql.Ext.Count(book.Id).ToValue()
ПЭ>}
ПЭ>

ПЭ>потому что на практике надо считать по подзапросу не один агрегат, а несколько.

Проанализировал я — дело непростое. То как вы записали выражение, это еще парсать и парсать.
Я записал его вот так, и все корректно. И блоками тоже можно достраивать.

var aggregates = from book in db.GetTable<Book>()
    select new
    {
        book.AuthorId,
        RN = Sql.Ext.RowNumber().Over().OrderBy(book.AuthorId).ToValue(),

        BooksCount = Sql.Ext.Count(book.Id).Over().PartitionBy(book.AuthorId).ToValue(),
        Count2 = Sql.Ext.Count(book.Title).Over().PartitionBy(book.AuthorId).ToValue(),
    };

aggregates = aggregates.Where(a => a.RN == 1);

var query = from author in db.GetTable<Author>()
    from a in aggregates.InnerJoin(a => a.AuthorId == author.Id)
    where a.BooksCount > 42
    select new
    {
        author.Name,
        BooksCount = a.BooksCount
    };


Если дадите сценарий более четко с типами запросов что будут, можно и солюшин придумать.
Клеить, напрмер можно так

int? minBookCount = 42;
int? minBookCount2 = null;

var query = from author in db.GetTable<Author>()
    select new
    {
        Author = author,

        BookCount = (from book in db.GetTable<Book>()
            where book.AuthorId == author.Id
            select book).CountExt(b => b.Id, Sql.AggregateModifier.None),

        BookCount2 = (from book in db.GetTable<Book>()
            where book.AuthorId == author.Id
            select book).CountExt(b => b.Id, Sql.AggregateModifier.None)
    };

if (minBookCount != null)
{
    query = query.Where(b => b.BookCount > minBookCount);
}

if (minBookCount2 != null)
{
    query = query.Where(b => b.BookCount2 > minBookCount2);
}

var resultQuery = from author in query
    select new
    {
        author.Author.Name,
        author.BookCount
    };


Тоесть задаем все возможные поля фильтра в первом запросе, а потом используем только части. linq2db лишнее откинет.