Как мне преобразовать общий подзапрос LINQ в метод?

2

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

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

Я добавил метод к классу страниц, называемому GetUserPermissions. Этот метод принимает UserId и возвращает класс non-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 для включения в качестве представления на данный момент.

Теги:
linq
linq-to-sql

3 ответа

0
Лучший ответ

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

Ошибка "член" 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>, а затем присоединяется к моему запросу к этому (как во втором примере).

1

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

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.

  • 0
    Спасибо, но ни один из этих вариантов не особенно привлекателен. Это потенциально большая таблица (и я собираюсь применить к ней разбиение на страницы и сортировку), поэтому ее перенос в IEnumerable, вероятно, не очень хорошая вещь. Переписывание кода разрешений в SQL - это то, чего я стараюсь избегать.
1

Возможно, вам нужен скомпилированный запрос?

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

  • 0
    Я исследую это дальше утром. Я подозреваю, что у него все еще будут проблемы с переводом членов PagePermissionSet в SQL, однако.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню