Subsonic 将SQL重组为亚音速LINQ

Subsonic 将SQL重组为亚音速LINQ,subsonic,Subsonic,我在菜单表中有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].[I

我在菜单表中有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中,只要有一条记录存在,它将返回数据的记录就无关紧要

我想我实际上想要一个像下面这样的联合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的菜单记录,相应的网页中有用户的角色。如果用户的角色不在网页中,那么我不想在结果中看到它

这里是我的CutoDown类,亚音速生成

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;}
}

似乎您可以在where子句中添加一个替代测试来实现这一点

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

尝试使用该方法查看数据库中的角色与用户的角色之间是否存在重叠

var test = Menu.All()
               .Where(x => x.PageID == null
                       || x.WebPages
                           .Any(pages => pages.Roles.Intersect(Roles.GetRolesForUser().Split(','))
                                            && pages.ID == x.PageID));

这看起来很简单!但是,如果我将网页作为菜单的属性,为什么我需要添加&&pages.ID==x.PageID?因为它是外键,为什么我需要添加它?因为您只想在我理解的情况下检查匹配页面的角色。如果忽略对PageID的检查,则如果集合中的任何页面与用户的角色关联,则将包括菜单。谢谢。我需要一个小小的调整,我一直坚持着。如果我获取当前Authenticated用户所处的所有角色,并将其与数据库中的Roles属性相匹配,则DB值可以是administrator,但Roles.GetRolesForUser可以是administrator、user、tech,因此包含操作将失败。您能帮忙吗?pages.Roles是一个字符串而不是字符串[],所以Intersect不起作用每页只有一个角色,或者它是以某种方式分隔的?如果每页只有一个角色,则可以绕过“包含”检查,查看当前角色是否包含页面角色。如果使用分隔符,则可能必须执行查询,然后使用一些字符串操作/匹配来筛选服务器端。我假设您有一个角色关联,而不是包含角色名称的列。