我有以下实体,基本上User
和Message
通过MsgGroup
建立了M2M关系。线程(或组)中的第一条消息也有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; }
}
我想为给定用户分组获取lates消息。特别是以下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)
};
然而,它会创建一个非常复杂的查询,其中每个消息字段都有子查询。
有解决方案吗?我也可以在基于方法的格式和查询表达式格式中提出相同的问题(因为我根本无法弄清楚查询表达式格式)
答案 0 :(得分:0)
我认为您可能正在寻求加入,也许是这样的,这将为您提供特定用户的最新消息,按线程ID排序,您可以在取部分包含您想要的邮件数量:
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对象。
答案 1 :(得分: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()
};
这为您提供了用户有消息的每个线程的最后一条消息。
答案 2 :(得分:0)
对于下面感兴趣的任何人,查询完全符合我的要求,但在我的问题中,仅使用JOIN
而不是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 } ;