Оптимизировать запрос Linq to SQL, группировать по нескольким полям - PullRequest
0 голосов
/ 26 июля 2010

Мой запрос LINQ содержит следующий оператор Group By:

Group p By Key = New With { _
.Latitude = p.Address.GeoLocations.FirstOrDefault(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)).Latitude, _
.Longitude = p.Address.GeoLocations.FirstOrDefault(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)).Longitude}

Запрос работает, но вот SQL, который выдает приведенный выше пункт

SELECT [t6].[Latitude]
            FROM (
                SELECT TOP (1) [t5].[Latitude]
                FROM [dbo].[GeoLocations] AS [t5]
                WHERE ([t5].[Granularity] IN (@p0, @p1)) AND ([t5].[AddressId] = [t2].[Addr_AddressId])
                ) AS [t6]
            ) AS [value], (
            SELECT [t8].[Longitude]
            FROM (
                SELECT TOP (1) [t7].[Longitude]
                FROM [dbo].[GeoLocations] AS [t7]
                WHERE ([t7].[Granularity] IN (@p2, @p3)) AND ([t7].[AddressId] = [t2].[Addr_AddressId])
                ) AS [t8]
            ) AS [value2]

Я не эксперт по SQL, но мне кажется, что это довольно неоптимальный перевод. Это действительно должен быть один запрос, который выбирает Latitide и Longitude из первой записи. Возможно, оптимизатор SQL Server позаботится об этом. Но есть ли способ подтолкнуть Linq для создания более тонкого оператора SQL для начала?

Я тоже попробовал следующее ..

Group p By Key = p.Address.GeoLocations.Where(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)). _
Select(Function(g) New With {.Latitude = g.Latitude, .Longitude = g.Longitude}).FirstOrDefault

но это привело к ошибке: «Группа по выражению может содержать только непостоянные скаляры, которые сопоставимы сервером».

1 Ответ

1 голос
/ 27 июля 2010

Извините, что отвечаю на c # ...

Вот что у вас есть, переведено на c #:

List<string> params = new List<string>()
{ "Address", "Point" };

from p in people
group p by new {
  Latitude = p.Address.GeoLocations
    .FirstOrDefault(g => params.Contains(g.Granularity)).Latitude,
  Longitude = p.Address.GeoLocations
    .FirstOrDefault(g => params.Contains(g.Granularity)).Longitude
};

Вот переписать, используя ключевое слово let.

from p in people
let loc = p.Address.GeoLocations
   .FirstOrDefault(g => params.Contains(g.Granularity))
group p by new
{
  Latitude = loc.Latitude,
  Longitude = loc.Longitude
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...