Это определенно вызов. Это некрасиво, но делает свое дело. Он возвращает именно то, что вы ищете. В случае сотрудников без присутствия вы возвращаете имя с нулевым временем.
var selectedDate = new DateTime(2009,4,28);
var query = from e in db.Employees
join a in db.Attendances on e.Id equals a.EmployeeId into Temp
from t in Temp.DefaultIfEmpty()
where t.SignInTime == null || (t.SignInTime >= selectedDate && t.SignInTime < selectedDate.AddDays(1))
group t by e.EmployeeName into grouped
select new
{
Employee = grouped.Key,
FirstSignInTime = grouped.Min(a => a.SignInTime),
LastSignOutTime = grouped.Max(a => a.SignOutTime)
};
Это SQL, который испускается этим выражением:
DECLARE @p0 DateTime = '2009-04-27 00:00:00.000'
DECLARE @p1 DateTime = '2009-04-28 00:00:00.000'
SELECT MIN([t1].[SignInTime]) AS [FirstSignInTime], MAX([t1].[SignOutTime]) AS [LastSignOutTime], [t0].[EmployeeName] AS [Employee]
FROM [Employee] AS [t0]
LEFT OUTER JOIN [Attendance] AS [t1] ON [t0].[Id] = [t1].[EmployeeId]
WHERE ([t1].[SignInTime] IS NULL) OR (([t1].[SignInTime] >= @p0) AND ([t1].[SignInTime] < @p1))
GROUP BY [t0].[EmployeeName]
Это очень близко к вашему исходному SQL. Я добавил где "t.SignInTime == null", чтобы он возвращал сотрудников с посещаемостью, но вы можете удалить это, если это не то, что вы хотите.