很少有GroupJoin在一个查询中

时间:2010-10-24 13:07:50

标签: c# extension-methods left-join objectquery

我正在尝试使用少量一致的GroupJoin编写ObjectQuery,这意味着应该有一个主表选择+几个额外的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 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

好吧,继续折磨LINQ可能会有用,虽然现在它似乎没用,LINQ可能只适用于包含一个表的短查询。它是为数组和XML,IMO创建的。

对于真正的 SQL查询,使用在EF实体中初始化的直接SQL查询会更好,如下所示:

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变体使用: