LINQ IQueryable帮助

时间:2009-06-24 10:13:19

标签: asp.net-mvc linq subsonic

我有一个Menu类,它有一个名为WebPages的IQueryable属性。在以下语句中,我将根据匹配返回Menu项,但我需要包含Webpages属性。这就是我现在所拥有的。

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

我需要扩展它以检查WebPage类中的属性,类似这样..

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

那不会编译,但我希望你能得到我想要做的事情。

注意:网页属性由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;}
}

4 个答案:

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

这应该只选择加入具有相应角色的页面的菜单项。

答案 1 :(得分:0)

尝试更改

public IQueryable<WebPage> WebPages

public IEnumerable<WebPage> WebPages

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

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

使用 Any()功能非常有效,因为它会在找到匹配后立即停止查看。

如果您使用 Where()然后 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;
            }
        }

答案 3 :(得分:0)

DoctorJonez谢谢!!!

我把它放在这里,因为我有更多的空间。我在Menu表中有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]))
  )

这是Subsonic中的一个错误还是我没有正确理解它?

Any()的问题是,只要有一条记录退出,在SQL中,无论哪条记录都返回数据都无关紧要。

我认为有效的我想要一个UNION SQL,但我不知道如何将其重新设计为C#/ Subsonic

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中,那么我不希望在我的结果中看到它。