在我的网站上,会员可以互相发送消息。 这是我的Message类:
public partial class Message
{
public System.Guid Id { get; set; }
public System.DateTime DateMsg { get; set; }
public string SenderId { get; set; }
public string ReceiverId { get; set; }
public string Text { get; set; }
}
我想做一个查询,获取每个已打开讨论的最后一条消息。由于我没有"讨论ID",我无法做到"按讨论ID"然后选择每个组中的第一个。 我该怎么办?
public IEnumerable<Message> Get_DiscussionsFor(string userId)
{
List<Message> list;
using (var context = new ModelContainer())
{
IQueryable<Message> dbQuery = context.Set<Message>();
list = dbQuery
.AsNoTracking()
.Where(m => m.SenderId.Equals(userId) || m.ReceiverId.Equals(userId))
.OrderByDescending(m => m.DateMsg)
.ToList<Message>();
}
return list;
}
答案 0 :(得分:2)
嗯,这可能有用,虽然它不会很快。
以下是查询的第一部分:
var list1 = dbQuery
.AsNoTracking()
.Where(m => m.SenderId.Equals(userId) || m.ReceiverId.Equals(userId));
我将创建另一个查询,它创建一个封装消息的匿名类型和另一个用户的ID。
var senderFirst = list1
.Where(m => m.SenderId.Equals(userId))
.Select(
m => {
Message = m,
OtherUser = m.ReceiverId
});
我正在创建另一个,这次是我们想要的用户是接收者,而其他用户是发件人:
var receiverFirst = list1
.Where(m => m.ReceiverId.Equals(userId))
.Select(
m => {
Message = m,
OtherUser = m.SenderId,
});
我现在正在联系他们。我可以这样做,因为它们具有相同类型和相同名称的完全相同的属性:在幕后,它们是相同的匿名类型。
var list2 = senderFirst.Concat(receiverFirst);
因此,涉及您所需用户的每条消息都将与标识为OtherUser
的其他用户一起显示。请注意,我们还没有更改Message
对象:它仍然存在,SenderId
和ReceiverId
的值正确。我们只是用另外的元数据将它包装在另一个对象中。
您说过涉及给定两个用户的任何消息都在同一个讨论中。因此,我们现在可以通过OtherUser
var list3 = list2.GroupBy(m => m.OtherUser);
所以现在我们已经分组了消息。您现在可以对每个组进行排序并选择最终消息。
var list4 = list3
.Select(g => g.OrderByDescending(m => m.Message.DateMsg).First());
现在你拥有了List<Message>
,因为你的Message
对象仍在那里,准备从封装中脱颖而出:
var list = list4
.Select(m => m.Message)
.ToList();