2010-10-24 6 views
1

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

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 .Inumerable, System.Func>, System.Func) ' не может быть выведен из использования. Попробуйте , указав аргументы типа явно.

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

Заранее благодарен.

ответ

0

Ну, это может быть полезно для продолжения пыток LINQ, хотя теперь это кажется бесполезным, и LINQ может быть правильным случаем только для краткого qu которые содержат одну таблицу. Он был создан для массивов и 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 [email protected]", ent 
); 
query.Parameters.Add(new ObjectParameter("ctry", "Australia")); 

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

+1

P.S. Метод «Включить» объединяет таблицы в геометрической прогрессии (известная ошибка), поэтому целесообразно только присоединиться к одной таблице, если будет больше одного, то в реальной таблице каждая таблица будет объединена столько раз, сколько «Include» будет использоваться в течение текущего запрос. – Anonymous

1

Вы пытаетесь с нетерпением загружать связанные объекты. Для этого используйте метод 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

Я думал, что я могу использовать Include только имя поля i merge tables, это то же самое. И в моем случае поля разные. LRS => LRS.RoleID, RLS => RLS.RoleId. Это также может быть - LRS => LRS.RoleID, RLS => RLS.EntityID – Anonymous

+1

В этом случае вы создали бы два свойства навигации. Каждое свойство навигации будет представлять собой другое отношение. –

Смежные вопросы