【问题标题】:LINQ - select query in related objects Entity Framework (EF4)LINQ - 在相关对象实体框架(EF4)中选择查询
【发布时间】:2023-03-20 16:00:02
【问题描述】:

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

所以,我基于 ContactThreadId 和 LoginId 我需要知道这个 LoginId 是否已经阅读了线程中的所有消息。如果不是,我需要用他/她的 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);

请帮忙。 谢谢

编辑

登录 - 此表保存登录/管理记录

Contact - 此表包含所有联系人(包括 Login 项,因为 Logins 也可以参与对话 - 可以回复消息等)当 LoginId 在联系人表中是NOT NULL,这意味着它是一个登录用户,否则它是一个公共用户提交消息。

QUESTION -> 每个 Login 只能有 1 个 Contact 记录(我有一个触发器在 Login 时创建 Contact 记录 创建)。我如何使它成为 1 比 1.?? 我从 ContactLogin 表中添加了一个 FK,但由于某种原因,EF 创建了 0..1 -> * 关联。它应该是 1 比 1。对于给定的登录名,只能有 1 个与该 LoginId 联系的联系人。

每当 Login 正在查看消息列表时,都会向该 Login 的 ContactReadState 插入一条新记录(标记该 Login 已阅读的消息(带有该 Login 的 ContactId)。

【问题讨论】:

  • 见鬼,你的格式真的很难阅读。我希望,我已经使换行符在逻辑上是正确的。

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


【解决方案1】:

我有一个片段,但无法将其完全组合在一起。特别是我不知道您将如何在新的ContactReadState 对象中设置ContactId(请参阅下面的???),因为显然给定的loginId 可以有很多联系人。那么,在新的读取状态中设置哪个?可能我误解了您模型中的某些内容,因为所有这些关系在我看来都非常复杂。

...基于 contactThreadIdloginId...

我直接使用上下文,您需要将其转换为您的存储库结构:

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 中正确创建这种一对一关系需要以下内容:

  • 您必须从Contact 表中删除LoginId 列和对应关系(这是EF 创建一对多关系的原因)。
  • Login 表中的LoginId 主键列不能是自动生成的标识。
  • 必须在ContactLogin表之间建立外键关系,同时Login中的外键列是主键列LoginId。因此,Login.LoginId(FK 的“依赖”)和Contact.ContactId(PK 的“主体”)之间的关系。

这意味着带有LoginId=xLogin 指的是带有ContactId=x(相同值)的Contact,这最终使得在上面的代码sn-p 中填充??? 变得容易:@987654340 @ 就是 = loginId

编辑 2

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

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

...通过...

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

(避免不必要地加入Contact 表)

【讨论】:

  • 斯劳马。我在上面添加了更多信息。另外,我在新编辑中还有另一个问题,也许你可以帮助我。谢谢
  • 您不认为这种方法在处理数百条记录时效果非常糟糕吗?这实际上意味着在这种情况下有数百个查询。那么数千条记录甚至更多呢?
猜你喜欢
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多