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