Как мне преобразовать общий подзапрос LINQ в метод? - PullRequest
2 голосов
/ 17 января 2010

Я изо всех сил пытаюсь найти правильные слова, чтобы подвести итог этой проблемы, поэтому любые замечания, которые я могу добавить, чтобы прояснить ее, будут оценены.

Основной сценарий таков: у меня есть базовая CMS (со страницами, пользователями и т. Д.). Страница - это объект данных LINQ, который отображается непосредственно в таблицу страниц.

Я добавил в класс Page метод GetUserPermissions. Этот метод принимает UserId и возвращает не-LINQ класс с именем PagePermissionSet, который описывает, что может делать пользователь. PagePermissionSet рассчитывается с помощью запроса LINQ.

Теперь я хочу получить список страниц, к которым у пользователя есть доступ. Идеальная реализация будет выглядеть следующим образом:

from page in mDataContext.Pages
where page.GetUserPermissions(userId).CanView
select page

Это завершается ошибкой, утверждая, что для GetUserPermissions не существует эквивалента SQL (что достаточно разумно) или после некоторого рефакторинга метода, что элемент CanView не может быть вызван для IQueryable.

Попытка два состояла в том, чтобы добавить метод к DataContext, который возвращает все разрешения для каждой страницы / пользователя в виде IQueryable:

IQueryable<PagePermissionSet> GetAllPagePermissions()

Затем я попытался присоединиться к этому набору результатов:

IQueryable<Page> GetAllPages(Guid? userId) {
    var permissions = mDataContext.GetAllPagePermissions();

    var pages =
        from page in mDataContext.WikiPages
        join permission in permissions on Page.FileName equals permission.PageName
        where permission.CanView && permission.UserId == userId
        select page;

    return pages;
}

Это приводит к ошибке: «У члена 'WikiTome.Library.Model.PagePermissionSet.PageName' нет поддерживаемого перевода в SQL."

PagePermissionSet - это всего лишь оболочка, содержащая данные из предложения select в GetUserPermissions, и инициализируется следующим образом:

select new PagePermissionSet(pageName, userName, canView, canEdit, canRename)

С учетом всего этого ... Как я могу использовать запрос LINQ в Page.GetUserPermissions в другом запросе? Я определенно не хочу дублировать код, и я бы предпочел не переводить его в SQL для включения в качестве представления на данном этапе.

Ответы [ 3 ]

1 голос
/ 17 января 2010

У вас есть несколько вариантов.

1) Быстрое и грязное решение состоит в том, чтобы использовать AsEnumerable() с вашим запросом, чтобы перенести всю таблицу Pages на клиентскую сторону, а затем работать с ней.Для небольших таблиц это подойдет, однако для больших таблиц это будет неэффективно и приведет к проблемам с производительностью в зависимости от размера.Если вы решите использовать это, помните, как это на самом деле работает.Это означает обновление вашего кода до:

from page in mDataContext.Pages.AsEnumerable()
where page.GetUserPermissions(userId).CanView
select page

2) Более сложным решением будет создание хранимой процедуры или UDF на сервере SQL, к которому вы будете обращаться из DataContext и передачи параметров.Взгляните на сообщение в блоге Скотта Гу: LINQ to SQL (часть 6 - извлечение данных с использованием хранимых процедур) .

Затем можно написать что-то вроде:

mDataContext.GetUserPermissions(userId)

Вся логика, которую вы выполняете в своем коде, будет написана на SQL, и вы вернете видимые страницы для данного пользователя.Это позволяет обойти использование PagePermissionSet свойств, которые не поддерживают перевод в SQL.

1 голос
/ 17 января 2010

Может быть, вам нужен скомпилированный запрос?

http://msdn.microsoft.com/en-us/library/bb399335.aspx

0 голосов
/ 18 января 2010

Мне удалось решить большую часть этой проблемы сегодня.

Ошибка «У члена 'WikiTome.Library.Model.PagePermissionSet.PageName' нет поддерживаемого перевода в SQL." было вызвано тем, КАК я инициализировал свои объекты PagePermissionSet.

Я инициализировал их с помощью конструктора, например:

select new PagePermissionSet(pageName, userName, canView, canEdit, canRename)

Однако, чтобы LINQ правильно отслеживал свойства, его нужно инициализировать следующим образом:

select new PagePermissionSet { PageName=pageName, UserName = userName, CanView = canView, CanEdit = canEdit, CanRename = canRename }

С этим изменением я могу создать метод, который возвращает IQueryable<PagePermissionSet>, а затем присоединить к нему мой запрос (как во втором примере).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...