2009-06-24 68 views
1

我有一个Menu类,它有一个名为WebPages的IQueryable属性。在下面的语句中,我返回基于匹配的菜单项,但我需要包含Webpages属性。这是我目前所拥有的。LINQ IQueryable帮助

var allCategories = Menu.All().Where(x => x.CategoryID == 4 && x.Visible) 

我需要扩展它的网页类检查属性,像这样..

var allCategories = Menu.All().Where(x => x.CategoryID == 4 && x.Visible && x.WebPages.Roles.Contains(User.Identity.Name)) 

这不会编译,但我希望你得到的JIST我试图去做。

注意:网页属性是由PageID而不是CategoryID填充的,但不知道这是否有所不同?

以下是我的课程简介。

public partial class Menu: IActiveRecord 
    { 
     public int ID {get; set;} 
     public int CategoryID {get;set;} 
     public bool Visible {get;set;} 
     public int PageID {get;set;} 
     public IQueryable<WebPage> WebPages 
     { 
      get 
      { 

        var repo=NorthCadburyWebsite.Models.WebPage.GetRepo(); 
        return from items in repo.GetAll() 
         where items.ID == _PageID 
         select items; 
      } 
     } 
} 

public partial class WebPage: IActiveRecord 
    { 
     public int ID {get;set;} 
     public string Roles {get;set;} 
} 

回答

0

这应该为你做队友。您只需说出WebPages.Any,如果任何菜单包含具有指定角色的网页,则这将返回true。

var allCategories = menus.Where(menu => menu.CategoryID == 1 && menu.Visible && menu.WebPages.Any(webPage => webPage.Roles.Contains(roleToSearchFor))); 

所以你需要添加的关键是这个。

menu.WebPages.Any(webPage => webPage.Roles.Contains(roleToSearchFor)) 

使用任何()功能是非常有效的,因为它会停止,只要找到一个匹配期待。

如果您使用凡(),然后COUNT()它会遍历所有的网页找到所有的比赛,然后遍历这些结果算来,所以这将是效率要低得多。

下面是一个完整的源代码示例供您尝试。

namespace DoctaJonez.TestingBrace 
    { 
     public partial class Menu //: IActiveRecord 
     { 
      public int ID { get; set; } 
      public int CategoryID { get; set; } 
      public bool Visible { get; set; } 
      public int PageID { get; set; } 
      public IQueryable<WebPage> WebPages { get; set; } 
     } 

     public partial class WebPage //: IActiveRecord 
     { public int ID { get; set; } public string Roles { get; set; } } 

     public static class Launcher 
     { 
      /// <summary> 
      /// The Main entry point of the program. 
      /// </summary> 
      static void Main(string[] args) 
      { 
       Menu myMenu1 = new Menu 
       { 
        ID = 1, 
        CategoryID = 1, 
        PageID = 1, 
        Visible = true, 
        WebPages = new List<WebPage>() 
        { 
         new WebPage { ID = 1, Roles = "Role1" }, 
         new WebPage { ID = 1, Roles = "Role2" }, 
         new WebPage { ID = 1, Roles = "Role3" }, 
        }.AsQueryable() 
       }; 

       Menu myMenu2 = new Menu 
       { 
        ID = 1, 
        CategoryID = 1, 
        PageID = 1, 
        Visible = true, 
        WebPages = new List<WebPage>() 
        { 
         new WebPage { ID = 1, Roles = "Role3" }, 
         new WebPage { ID = 1, Roles = "Role4" }, 
         new WebPage { ID = 1, Roles = "Role5" }, 
        }.AsQueryable() 
       }; 

       Menu myMenu3 = new Menu 
       { 
        ID = 1, 
        CategoryID = 1, 
        PageID = 1, 
        Visible = true, 
        WebPages = new List<WebPage>() 
        { 
         new WebPage { ID = 1, Roles = "Role5" }, 
         new WebPage { ID = 1, Roles = "Role6" }, 
         new WebPage { ID = 1, Roles = "Role7" }, 
        }.AsQueryable() 
       }; 

       List<Menu> menus = new List<Menu>() { myMenu1, myMenu2, myMenu3 }; 

       string roleToSearchFor = "Role3"; 

       var allCategories = menus.Where(menu => menu.CategoryID == 1 && menu.Visible && menu.WebPages.Any(webPage => webPage.Roles.Contains(roleToSearchFor))).ToList(); 

       return; 
      } 
     } 
0

尝试改变

public IQueryable<WebPage> WebPages 

public IEnumerable<WebPage> WebPages 

我认为LINQ查询返回的IEnumerable ...

0

DoctorJonez感谢!

我把这个放在这里,因为我有更多的空间。我有11条记录中的菜单表,只有1个有PAGEID一套但是如果我用

var test = Menu.All().Where(x => x.WebPages.Any(pages => pages.Roles.Contains(Roles.GetRolesForUser()[0]) 

我得到11个记录作为SQL运行是这个

SELECT [t0].[CategoryID], [t0].[CreatedBy], [t0].[CreatedOn], [t0].[ID], [t0].[ImageID], [t0].[ImageIDHover], [t0].[Locale], [t0].[ModifiedBy], [t0].[ModifiedOn], [t0].[OrderID], [t0].[PageID], [t0].[ParentID], [t0].[Title], [t0].[URL], [t0].[Visible] 
FROM [dbo].[Menu] AS t0 
WHERE EXISTS(
    SELECT NULL 
    FROM [dbo].[WebPage] AS t1 
    WHERE ([t1].[Roles] LIKE '%' + 'User' + '%') 
) 

如果我运行此我得到的1结果

var test = Menu.All().Where(x => x.WebPages.Any(pages => pages.Roles.Contains(Roles.GetRolesForUser()[0]) && pages.ID == x.PageID)); 

这种情况的SQL是

SELECT [t0].[CategoryID], [t0].[CreatedBy], [t0].[CreatedOn], [t0].[ID], [t0].[ImageID], [t0].[ImageIDHover], [t0].[Locale], [t0].[ModifiedBy], [t0].[ModifiedOn], [t0].[OrderID], [t0].[PageID], [t0].[ParentID], [t0].[Title], [t0].[URL], [t0].[Visible] 
FROM [dbo].[Menu] AS t0 
WHERE EXISTS(
    SELECT NULL 
    FROM [dbo].[WebPage] AS t1 
    WHERE (([t1].[Roles] LIKE '%' + 'User' + '%') AND ([t1].[ID] = [t0].[PageID])) 
) 

这是亚音速中的错误还是我没有正确理解它?

Any()的问题在于,只要有一条记录退出,SQL就会返回数据。

我觉得有效,我想一个UNION SQL像下面,但我不知道我是怎么重新设计是为C#/亚音速

select m.* from menu m where pageid is null 

union 

select m.* from menu m 

join webpage p 
on p.id = m.pageid 

where p.roles like '%User%' 

我想回到所有菜单的记录,并为那些与PageID设置相应的WebPage具有用户在其中的角色。如果用户的角色不在WebPage中,那么我不想在我的结果中看到它。

+0

您可以编辑您的问题以包含此信息,因为它似乎是问题的更多细节而不是答案。 – CoderDennis 2009-06-24 19:11:54

1

如果我理解正确的问题,你想是这样的:

var menuItems = 
    from menuItem in Menu.All() 
     where menuItem.Visible 
      and (
       menuItem.WebPages.Contains(
        webPage => webPage.Roles.Contains(
         "role" 
        ) 
       ) 
       or menuItem.PageIsNull 
      ) 
     select menuItem; 

这应该只选择菜单项加入与合适的角色页面。

+0

我需要那些PageID为空的地方。 – Jon 2009-06-26 08:26:33