Несколько GroupJoin в одном запросе - PullRequest
1 голос
/ 24 октября 2010

Я пытаюсь написать ObjectQuery с несколькими непротиворечивыми GroupJoin, это означает, что должен быть один основной выбор таблицы + несколько дополнительных LEFT JOIN Я делаю это следующим образом, с помощью метода SelectMany, потому что без него я не могу получить доступ к полю RoleID:

var routesQuery = entities.Routes.Join(
                    entities.Locales,
                    Routes => Routes.LocaleID,
                    Locales => Locales.LocaleID,
                    (Routes, Locales) => new { Routes = Routes }
                ).GroupJoin(
                    entities.LinkRolesPermissions,
                    Routes => Routes.Routes.RouteID,
                    LinkRolesPermissions => LinkRolesPermissions.EntityID,
                    (Routes, LinkRolesPermissions) => new 
                    { 
                        LinkRolesPermissions = LinkRolesPermissions,
                        RoleID = LinkRolesPermissions.SelectMany(
                            LRS => LRS.RoleID,
                            (LRS, RoleID) => new { RoleID = LRS.RoleID }
                        )
                    }
                )
                .SelectMany(
                    LinkRolesPermissions => LinkRolesPermissions.RoleID, 
                    (LinkRolesPermissions, RoleID) => new { RoleID = RoleID }
                 ).GroupJoin(
                    entities.aspnet_Roles, 
                    LRS => LRS.RoleID, 
                    RLS => RLS.RoleId, 
                    (LRS, RLS) => new { LRS = LRS }
                );

Все работает, НО он каким-то образом работает как INNER JOIN, я понял, что метод SelectMany вызывает такое поведение. Он генерирует этот запрос:

SELECT  1 AS [C1],  1 AS [C2],  [Extent3].[RoleID] AS [RoleID] FROM   [dbo].[Routes] AS [Extent1] 
INNER JOIN [dbo].[Locales] AS [Extent2] ON ([Extent1].[LocaleID] = [Extent2].[LocaleID]) OR (([Extent1].[LocaleID] IS NULL) AND ([Extent2].[LocaleID] IS NULL)) 
INNER JOIN [dbo].[LinkRolesPermissions] AS [Extent3] ON ([Extent1].[RouteID] = [Extent3].[EntityID]) OR (([Extent1].[RouteID] IS NULL) AND ([Extent3].[EntityID] IS NULL))

Я удалил его и получил следующую ошибку:

var routesQuery = entities.Routes.Join(
                    entities.Locales,
                    Routes => Routes.LocaleID,
                    Locales => Locales.LocaleID,
                    (Routes, Locales) => new { Routes = Routes }
                ).GroupJoin(
                    entities.LinkRolesPermissions,
                    Routes => Routes.Routes.RouteID,
                    LinkRolesPermissions => LinkRolesPermissions.EntityID,
                    (Routes, LinkRolesPermissions) => new 
                    { 
                        LinkRolesPermissions = LinkRolesPermissions,
                        RoleID = LinkRolesPermissions.SelectMany(
                            LRS => LRS.RoleID,
                            (LRS, RoleID) => new { RoleID = LRS.RoleID }
                        )
                    }
                )
                .GroupJoin(
                    entities.aspnet_Roles, 
                    LRS => LRS.RoleID, 
                    RLS => RLS.RoleId, 
                    (LRS, RLS) => new { LRS = LRS }
                );

Аргументы типа для метода «System.Linq.Enumerable.SelectMany (System.Collections.Generic.IEnumerable, System.Func> System.Func)» не может быть выведено из использования. Пытаться указание аргументов типа явно.

Может кто-нибудь объяснить мне такое поведение, пожалуйста, и посоветовать, как это исправить, если это возможно.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 27 октября 2010

Вы пытаетесь загружать связанные объекты. Для этого используйте метод Include.

http://msdn.microsoft.com/en-us/library/bb896272.aspx

IQueryable<Route> query = 
  from route in entities.Routes.Include("LinkRolesPermissions.aspnet_Roles")
  where route.Locales.Any()
  select route;

Чтобы это работало, вам нужно настроить свойства навигации.

http://msdn.microsoft.com/en-us/library/bb738520.aspx


PS: вам не нужно каждый раз проецировать на анонимный тип:

(Routes, Locales) => new { Routes = Routes } 

Может быть

(Routes, Locales) => Routes
0 голосов
/ 26 февраля 2011

Что ж, было бы полезно продолжать пытать LINQ, хотя теперь это кажется бесполезным, и LINQ может быть правильным случаем только для коротких запросов, содержащих одну таблицу. Он был создан для массивов и XML, IMO.

Для реальных SQL-запросов было бы намного лучше использовать прямой SQL-запрос, инициализированный внутри сущности EF, например:

ObjectQuery<DbDataRecord> query = new ObjectQuery<DbDataRecord>
(
"SELECT c.Name,c.City, d.Name FROM ContosoEntities.Customer as c " + 
"LEFT JOIN ContosoEntities.Products as d ON d.Name = c.Name " + 
"WHERE c.Country=@ctry", ent
);
query.Parameters.Add(new ObjectParameter("ctry", "Australia"));

Все варианты использования EF перечислены здесь:

...