LINQ - 在相关对象中选择查询实体框架(EF4)

时间:2011-11-30 14:00:40

标签: linq entity-framework linq-to-entities

对于以下内容(我正在使用EF4),我需要选择一个线程中的所有消息( ContactThreadId ),这些消息在给定LoginId时尚未读取

enter image description here

所以,我基于ContactThreadId和LoginId,我需要知道这个LoginId是否已经读取了Thread中的所有消息。如果不是,我需要使用他/她的LoginId更新 ContactReadState 以及来自线程的所有消息以及何时阅读。

我尝试了这些但是被卡住了:

// 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时在联系人表中 NOT NULL ,这意味着它是登录用户,否则它是公共用户提交邮件。

问题 - >每个登录只能包含1个联系人记录(我有一个触发器,可在登录创建时创建联系记录) 。我该怎么做才能让它为1比1。 我已经从联系添加了一个FK到登录表,但由于某种原因,EF创建了0..1 - > *协会。它应该是1到1.对于给定的登录,只能有1个与LoginId的联系。

每当Login正在查看消息列表时,会向该Login的ContactReadState插入一条新记录(标记该Login读取的消息(使用ContactId进行该登录)。

1 个答案:

答案 0 :(得分:2)

我有一个片段,但不能完全放在一起。特别是我不知道如何在新的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主键列不得为自动生​​成的标识。
  • 您必须在ContactLogin表之间创建外键关系,其中Login中的外键列同时是主键列LoginId。因此,关系介于Login.LoginId(与FK“相关”)和Contact.ContactId(与PK的“主体”)之间。

这意味着Login LoginId=x引用Contact ContactId=x(相同值),最终可以轻松填充???在上面的代码段中:???只是= loginId

修改2

...当然你可以在查询中替换...

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

... ...通过

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

(这避免了对Contact表的unnessacary连接)