Возврат непрочитанных записей с использованием Linq To SQL

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

Вот моя структура таблицы...

Документы (первичный ключ = идентификатор)
ID, заголовок, LatestApprovedRevID

Редакции (Первичный ключ = ID)
ID, DocumentID, RevisionNum, Body

Document_Reads (первичный ключ = DocumentID, имя пользователя)
DocumentID, UserName, RevisionID

Когда пользователь открывает документ, открывается последняя утвержденная ревизия, и в Document_Reads вставляется запись, показывающая документ и ревизию, которые прочитал пользователь. Я хотел бы знать, как сделать запрос с использованием Linq для возврата документов, которые НЕ были прочитаны UserName (текущий аутентифицированный пользователь).

Чтобы получить список непрочитанных документов, есть три случая, когда я хотел бы вернуть документ:

  • если документ не имеет записей в Document_Reads.
  • если документ имеет записи в Document_Reads, но ни одна из них не предназначена для UserName.
  • если документ имеет записи в Document_Reads и существует запись для UserName, но Document_Reads.RevisionID не соответствует Documents.LastApprovedRevID.

Я написал функцию фильтра, но у меня проблемы с написанием запроса для 2-го требования. Он вернет документ, если найдены какие-либо Document_Reads, которые не совпадают с UserName.

<Runtime.CompilerServices.Extension()> _
Public Function FilterLatestUnread(ByVal query As IQueryable(Of Document), ByVal userName As String) As IQueryable(Of Document)

    'Documents with no document_reads
    Dim q As IQueryable(Of Document) = From d In query _
                                       Where d.Document_Reads.Count = 0 _
                                       Select d

    'documents with document_reads but none for userName
    q = q.Union(From d In query _
                From dr In d.Document_Reads _
                Where Not (dr.UserName = userName) _
                Select d)

    'documents with document_reads for userName but RevisionID does not match LastApprovedRevID
    q = q.Union(From d In query _
                From dr In d.Document_Reads _
                Where dr.UserName = userName And _
                Not (dr.RevisionID = d.LastApprovedRevID) _
                Select d)

    'Return the combined query.
    Return q

End Function

Затем мой репозиторий возвращает все документы с утвержденной ревизией и использует фильтр как...

return _repository.List().FilterLatestUnread("John Doe").ToList()

Спасибо за любую помощь, и я прошу прощения, если эту тему уже можно найти на этом сайте... Я не был уверен, что мне нужно искать.

2 ответа

Решение

Обновление: я столкнулся с другой ошибкой, связанной с попыткой объединения запросов с другим числом выражений. Это то, что я должен был сделать, чтобы исправить это в конце...

return From d In query _
       Where (d.Document_Reads.Count = 0) Or _
       (From dr In d.Document_Reads _
        Where dr.UserName = userName _
        Select dr).Count = 0 Or _
        (From dr In d.Document_Reads _
         Where dr.UserName = userName And _
         Not (dr.RevisionID = d.LastApprovedRevID) _
         Select dr).Count = 1 _
         Select d

Я думаю, что я понял это.

Для второго запроса я использую этот код:

 q = q.Union(From d In query _
                Where (From dr In d.Document_Reads _
                       Where dr.UserName = userName _
                       Select dr).Count = 0 _
                       Select d)

Спасибо Rap за помощь в обсуждении!

Другие вопросы по тегам