2

我有以下实体,基本上UserMessage通过MsgGroup. 线程(或组)中的第一条消息也有ThreadId=MessageId,其他人共享相同的ThreadId

public class User
{
    public int UserId { get; set; }
    [System.ComponentModel.DataAnnotations.Schema.InverseProperty("Received")]
    public virtual System.Collections.Generic.ICollection<MsgGroup> ReceivedGroups { get; set; }
}

public class Message
{
    public int MessageId { get; set; }
    public int ThreadId { get; set; }
    public virtual System.Collections.Generic.ICollection<MsgGroup> MsgGroups { get; set; }
}

public class MsgGroup
{
    public int MsgGroupId { get; set; }

    public int UserId { get; set; }
    public virtual User Received { get; set; }

    public int MessageId { get; set; }
    public virtual Message Message { get; set; }
}

我想为给定用户在组中获取迟到的消息。特别是以下 SQL 查询:

select * from messages where MessageId IN (
    SELECT MaxId FROM (
        select ThreadId , MAX(MessageId) as MaxId from messages where ThreadId in (
            select distinct MessageId from msggroups where UserId = 1
        ) 
        GROUP BY ThreadId
    ) AS t1
)

我努力了:

var query = from grp in db.MsgGroups.Where(g => g.UserId == userId)
select new
{
    f = (from msg in db.Messages where (msg.ThreadId == grp.MessageId) select msg).OrderByDescending(m => m.Date).Take(1)
};

但是,它会创建一个非常复杂的查询,其中每个消息字段都有子查询。

有解决办法吗?我也可以在基于方法的格式和查询表达式格式中问同样的问题吗(因为我根本无法弄清楚查询表达式格式)

4

3 回答 3

0

我认为您可能正在寻找加入,可能是这样的,这将为您提供特定用户的最新消息,按线程 ID 排序,您可以将Take部分中的 100 替换为您想要的消息数量:

var query = (from grp in db.MsgGroups
    .Join(
        db.Messages,
        g => g.MessageId,
        m => m.ThreadId,
        (g, m) => new { grp = g, mgs = m })
        .Where(x => x.grp.UserId == userId)
    select new
    {
        Message = grp.mgs
    })
    .Take(100)
    .OrderByDescending(t => t.Message.ThreadId);

这将为您提供一组匿名对象,每个对象都有一个名为 Message 的属性,即您想要的 Message 对象。

于 2013-10-29T08:43:51.807 回答
0

对于任何对以下查询感兴趣的人都完全按照我的要求进行了操作,唯一的区别是它在我的问题中使用JOIN了 s 而不是s:IN

var query = 
from mm in
(
    from grp in db.MsgGroups.Where(g => g.UserId == userId)
    from msg in db.Messages
    where msg.ThreadId == grp.MessageId
    group msg by msg.ThreadId into thr
    select new { t = thr.Key, m = thr.Max(t => t.MessageId) }
)
join omsg in db.Messages
on mm.m equals omsg.MessageId
select new { t = mm.t, m = omsg.Text } ;
于 2013-10-29T16:58:42.600 回答
0

使用导航属性并让 EF 处理 SQL 连接:

var query = from rg in db.MsgGroups
            where rg.UserId == userId
            group rg by rg.ThreadId into thread
            select new { 
                         Thread = thread.Key, 
                         LastMessage = thread.Select(t => t.Message)
                                             .OrderByDescending(m => m.Date)
                                             .FirstOrDefault()
                       };

这将为您提供用户有消息的每个线程的最后一条消息。

于 2013-10-29T09:34:56.247 回答