我有一个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;}
}
答案 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中,那么我不希望在我的结果中看到它。