返回具有与userId LINQ匹配的最新时间戳的实体

tes*_*ern 3 c# linq-to-entities asp.net-mvc-3

我坚持这个.我有两个表:Users2Users和ActivityLog.我想查找作为用户朋友的Users2Users列表,并根据其Timestamp返回每个最新活动,然后检查它是什么类型.

Users2Users
int UserId
int TypeOfLink
int FriendId

ActivityLog
int Type
int UserId
DateTime Timestamp
Run Code Online (Sandbox Code Playgroud)

似乎令我不安的是获取ActivityLog实体而不是Timestamp值.

我的friendList查询如下所示:

var friendList = (from u in db.Users2Users
where u.UserId == userId || u.FriendId == userId
&& u.TypeOfLink == 2 // confirmed as friend
orderby u.User.ScreenName ascending
select u).Distinct().ToList();
Run Code Online (Sandbox Code Playgroud)

之后我打算尝试一个foreach,但是如何返回ActivityLog实体而不是Timestamp呢?

// get their last activity
foreach (var user in domusers)
{
    var act = (from a in db.ActivityLogs
    where a.UserId == user.UserId
    select a.Timestamp).Max();
    // other stuff
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*age 8

您可以通过Timestamp选择条目并选择第一个元素:

var act = db.ActivityLogs
  .Where(a => a.UserId == user.UserId)
  .OrderByDescending(a => a.Timestamp)
  .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

或者使用查询语法:

var act = (from a in db.ActivityLogs 
where a.UserId == user.UserId
orderby a.Timestamp descending
select a).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

请注意,如果源集合中没有元素,您将获得null结果.

使用OrderByDescending有点无效,因为它会对所有活动进行排序.在集合上执行单次传递并找到具有最新元素的元素更有效Timestamp.你可以使用Aggregate.在这里,我假设你能够创建一个"null" Activity,其中Timestamp属性具有默认(和最小值)DateTime:

var nullActivity = new Activity(); // nullActivity.Timestamp == DateTime.MinValue
var activity = db.ActivityLogs
   .Where(a => a.UserId == user.UserId)
   .Aggregate(
     nullActivity,
     (accumulate, value) => value.Timestamp >= accumulate.Timestamp ? value : accumulate
   );
if (activity != nullActivity)
  // The latest activity was found
Run Code Online (Sandbox Code Playgroud)

如果您无法创建"null"活动,因为种子Aggregate可以使用匿名类型来跟踪最新的时间戳和相关活动,但这样做稍微繁琐.