我有一个Logins
表,用于记录用户login
,logout
或loginFailed
及其时间戳。现在,我想在最后loginFailed
之后获取login
的列表,并在24小时内发现loginFailed
。
我现在正在做的是先获取最后一次登录时间戳。然后使用第二个查询来获取最终列表。你认为我应该一起加入这两个问题吗?为什么不?为什么是?如果是的话怎么样?
var lastLoginTime = (from inRecord in db.Logins
where inRecord.Users.UserId == userId
&& inRecord.Action == "I"
orderby inRecord.Timestamp descending
select inRecord.Timestamp).Take(1);
if (lastLoginTime.Count() == 1)
{
DateTime lastInTime = (DateTime)lastLoginTime.First();
DateTime since = DateTime.Now.AddHours(-24);
String actionStr = "F";
var records = from record in db.Logins
where record.Users.UserId == userId
&& record.Timestamp >= since
&& record.Action == actionStr
&& record.Timestamp > lastInTime
orderby record.Timestamp
select record;
}
答案 0 :(得分:4)
从长远来看,我认为这不重要。无论您如何在LINQ to SQL中实际构建查询,数据库服务器上的最终事件序列都将是
现在......将其作为单个查询的一部分进行操作将节省实际日期时间的往返次数,因此您可以通过这种方式获得一些性能。但我建议你只是尝试合并它们,如果你绝对需要,因为你的性能分析表明查询是一个瓶颈。
答案 1 :(得分:4)
我认为您不应该将它们组合在一起,因为您当前的查询非常易读。我认为如果将它们合并在一起,就会更难理解代码。
答案 2 :(得分:1)
由于其他人已经说过的原因,我不会合并,但您可以稍微简化第一个查询:而不是
orderby inRecord.Timestamp descending
select inRecord.Timestamp).Take(1);
你可以简单地说:
select inRecord.Timestamp).Max();
它会做同样的事情,但它比你的方式更清晰。
答案 3 :(得分:1)
您还可以使用IQueryable对象来编写更复杂的查询,并且仍然可以使代码非常易于阅读。 (我混合了扩展语法和查询语法,只是为了表明它可以完成。您可以像解决方案中的任何其他代码一样轻松地交换此代码以将其分开。)
var usersRecords = db.Logins.Where(r => r.Users.UserId == userId);
var userLoginTimes = usersRecords.Where(r => r.Action == "I")
.Select(r => r.Timestamp);
var usersFunctions = usersRecords.Where(r => r.Action == "F");
var records = from record in usersFunctions
where userLoginTimes.Any()
let lastLoginTime = userLoginTimes.Max()
where record.Timestamp >= since
&& record.Timestamp > lastLoginTime
select record;