LINQ - выбор запроса в связанных объектах Entity Framework (EF4) - PullRequest
2 голосов
/ 30 ноября 2011

Для следующего (я использую EF4) мне нужно выбрать все сообщения в теме ( ContactThreadId ), которые еще не были прочитаны, учитывая LoginId

enter image description here

Итак, я основан на ContactThreadId и LoginId. Мне нужно знать, прочитал ли этот LoginId все сообщения в теме. Если нет, мне нужно обновить ContactReadState со всеми сообщениями из цепочки с его / ее LoginId и когда она / он прочитает его.

Я пробовал это, но застрял:

// Update read state
var thread = this.contactMessageThreadRepository.GetRow(id);
var loginEntity = this.loginRepository.GetRow(ProfileContext.LoginId);

var unreadMsg = loginEntity.Contact
  .Where(x => x.ContactThread.Any(y => y.ContactThreadId == id))
  .Select(b => b.ContactMessage.FirstOrDefault())
  .Where(q => q.ContactReadState.Count() == 0);

var unreadMsg = loginEntity.Contact
  .Where(x => x.ContactThread.Any(y => y.ContactThreadId == id))
  .Where(y => y.ContactReadState.Any(q => q.ContactId != loginEntity.ContactId));

var msg = thread.Contact
  .Where(x => x.LoginId == loginEntity.LoginId)
  .Where(y => y.ContactReadState.Count() == 0);

пожалуйста, помогите. спасибо

РЕДАКТИРОВАТЬ :

Логин - эта таблица содержит логины / записи администратора

Контакт - в этой таблице хранятся все контакты (включая Вход элементов, поскольку логины могут также участвовать в беседе, могут отвечать на сообщения и т. Д.) Когда LoginId в таблице контактов НЕ НУЛЬ , это означает, что это Логин пользователь, в противном случае это публичный пользователь , отправляющий сообщение.

ВОПРОС -> Каждый Логин может иметь только 1 Контакт запись (У меня есть триггер, который создает Контакт запись при Логин создание). Как мне сделать так, чтобы было 1 к 1. ?? Я добавил FK из таблицы Contact в Login , но по какой-то причине EF создал ассоциацию 0..1 -> *. И это должно быть от 1 до 1. Для данного логина может быть только 1 контакт с этим логином.

Всякий раз, когда при входе в систему просматривается список сообщений, в ContactReadState для этого входа в систему добавляется новая запись (отмечается сообщение, прочитанное этим именем входа (с ContactId для этого имени входа).

1 Ответ

2 голосов
/ 30 ноября 2011

У меня есть фрагмент, но я не могу собрать его полностью вместе. Особенно я не знаю, как бы вы установили ContactId в новых ContactReadState объектах (см. ??? ниже), потому что, очевидно, у данного loginId может быть много контактов. Итак, какой из них установить в новых состояниях чтения? Возможно, я что-то неправильно понял в вашей модели, потому что все эти отношения кажутся мне очень сложными.

... на основе contactThreadId и loginId ...

Я использую контекст напрямую, вам нужно перевести это в структуру вашего хранилища:

using (var context = new MyContext())
{
    var unreadMsgs = context.ContactMessages
        .Where(cm => cm.ContactThreadId == contactThreadId
                  && !cm.ContactReadState
                         .Any(crs => crs.Contact.LoginId == loginId))
        .ToList();
    // These should be the unread messages you want to select.

    // Now, updating ContactReadState:
    foreach(var unreadMsg in unreadMsgs)
    {
        var newContactReadState = new ContactReadState
        {
            ContactMessageId = unreadMsg.ContactMessageId,
            ContactId = ???,
            ReadDate = DateTime.Now
        };
        context.ContactReadStates.AddObject(newContactReadState);
    }

    context.SaveChanges();
}

Редактировать

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

Для создания такого отношения один-к-одному в EF требуется следующее:

  • Вы должны удалить столбец LoginId и соответствующие отношения из таблицы Contact (это причина создания отношения EF "один-ко-многим").
  • Столбец первичного ключа LoginId в таблице Login не должен быть автоматически сгенерированным идентификатором.
  • Необходимо создать отношение внешнего ключа между таблицами Contact и Login, где столбец внешнего ключа в Login является одновременно столбцом первичного ключа LoginId. Таким образом, связь между Login.LoginId («зависимый» с FK) и Contact.ContactId («главный» с PK).

Это будет означать, что Login с LoginId=x относится к Contact с ContactId=x (то же значение), что в итоге позволяет легко заполнить ??? в фрагменте кода выше: ??? is просто = loginId.

Редактировать 2

... и, конечно, вы можете заменить в запросе ...

.Any(crs => crs.Contact.LoginId == loginId)

... по ...

.Any(crs => crs.ContactId == loginId)

(что позволяет избежать необязательного объединения таблицы Contact)

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