LINQ-to-SQL: возвращает свойство «массив строк» ​​(или столбец) для каждой строки - PullRequest
0 голосов
/ 21 октября 2018

Простой запрос для Groups приводит к другому запросу для каждого из его результатов:

using (var db = new DataClasses1DataContext())
{
    db.Log = Console.Out;

    var query = from g in db.Groups
                let stats = from s in g.GroupCountryStats
                            select new
                            {
                                s.CountryId,
                                s.MembersCount
                            }
                select new
                {
                    g.ObjectId,
                    g.Name,
                    Stats = stats.ToArray()
                };

    var single = query.First(); // Take(2) would result in 2 extra calls, 3 in 3 and so on...
}

Вывод на консоль (журнал поставщика Linq-to-Sql):

SELECT TOP (1) [t0].[ObjectId] AS [ObjectId], [t0].[Name]
FROM [dbo].[Groups] AS [t0]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.7.3056.0

SELECT [t0].[CountryId] AS [CountryId], [t0].[MembersCount]
FROM [dbo].[GroupCountryStats] AS [t0]
WHERE [t0].[GroupId] = @x1
-- @x1: Input Int (Size = -1; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.7.3056.0

Press any key to continue . . .

Я хотел бы получить все данные в одном запросе вместо N + 1 запросов.

Я пытался использовать DataLoadOptions, с LoadWith<Group>(T=>T.GroupCountryStats), но результат не изменился.Linq2Sql по-прежнему совершает более 1 вызова в базу данных.

Как избежать этого и получить все, что мне нужно, за один вызов?

1 Ответ

0 голосов
/ 21 октября 2018

Это ошибка (или в лучшем случае недостаток) в LINQ-to-SQL.Запрос без First или Take преобразуется в один порядочный запрос SQL, содержащий OUTER JOIN.Но, конечно, это даст вам все групп.

Когда LINQ-to-SQL сталкивается с операторами, которые ограничивают число результатов, кажется, что они запрограммированы на применение их к корню.только сущность, а затем запросить присоединяющиеся сущности отдельно.

Самое смешное: это не происходит, когда объединяются Skip и Take.Таким образом, в качестве хака вы можете использовать Skip(0).take(x), например:

var results = query.Skip(0).Take(3).ToList();

Если вам нужен один результат, вы должны сделать:

var results = query.Skip(0).Take(1).AsEnumerable().First();

Без .AsEnumerable() снова будетрецидив на 1 + 1 запросов.(Я предполагаю, что перевод SQL First имеет приоритет в форме запроса).

Это грязный хак, необходимый для борьбы с неплотными абстракциями IQueryable.Убедитесь, что, если вы решите использовать его, вы хорошо прокомментируете его в коде.

Последний комментарий: возможно, вам следует рассмотреть возможность перехода на более продвинутый ORM, такой как Entity Framework.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...