Реинжиниринг SQL в SubSonic LINQ - PullRequest
0 голосов
/ 24 июня 2009

У меня есть 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 # / 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, указывается, что соответствующая веб-страница имеет роль пользователя. Если роль пользователя отсутствует на веб-странице, я не хочу видеть ее в своих результатах.

Вот мои классы cutodwn, которые генерирует Subsonic

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

1 Ответ

0 голосов
/ 24 июня 2009

Похоже, что вы можете просто добавить альтернативный тест в предложение where для этого.

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

EDIT

Попробуйте использовать метод Intersect, чтобы проверить, не перекрываются ли роли в БД и роли для пользователя.

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