Вы можете значительно оптимизировать подобные операции, используя DBContext с отношениями, которые ориентированы на то, как вы хотите их запрашивать.В вашем случае у вас есть компьютеры Departments / w и свободный DbSet of EventLogs.Субъекту компьютера обычно не требуется набор журналов событий, но в случае с этим отчетом это соотношение 1-много было бы полезно.
Если в вашем основном контексте эти отношения не отображаются, то вы можете рассмотреть ограниченный контекст для извлечения этих данных с использованием карт сущностей, при этом компьютер рассматривается как объект верхнего уровня, а на каждом компьютере есть отдел,и коллекция EventLogs.Каждое событие имеет ссылку на пользователя, основанную на его идентификаторе пользователя.
Оттуда EF может выполнить всю тяжелую работу:
var sessionDataQuery = dbContext.Computers
.Select(x => new
{
x.Department.DepartmentId,
x.Department.DepartmentName,
x.ComputerId,
ComputerName = x.Name,
LoginEvents = x.EventLogs
.OrderBy(e => e.EventDateTime)
.Where(e => e.EventType = 11)
.Select(e => new
{
e.EventId,
e.User.UserId,
e.User.UserName,
e.EventDateTime
}.ToList(),
LogoutEvents = x.EventLogs
.OrderBy(e => e.EventDateTime)
.Where(e => e.EventType = 12)
.Select(e => new
{
e.EventId,
e.User.UserId,
e.User.UserName,
e.EventDateTime
}.ToList()
});
Этот запрос должен дать вам IQueryable данных, которые вы можетеиспользуйте, чтобы начать строить детали вашего сеанса.Поскольку он будет работать на всех компьютерах, вы, вероятно, захотите избегать использования на нем .ToList (), вместо этого используйте To & skip / w ToList для извлечения пакета из них (т.е. 50 одновременно).) или выполнить итерацию и выбрать их по одному в Foreach.
Предполагается, что ссылка на пользователя события будет соответствовать отделу компьютера.
Отсюда вы можете оценить LoginEvents и LogoutEvents каждого компьютера и составить модели представления сеанса для них.Скорее всего, вам понадобится логика для объединения входов в систему с выходом из системы на основе времени и обработки случаев, когда у вас может быть вход в систему без выхода из системы и тиски.
Предполагается, что для выходаЗаполнение парсинга будет примерно таким:
foreach(var computer in sessionDataQuery)
{
for(int count = 0; count < computer.LoginEvents.Count; count++)
{
var loginEvent = computer.LoginEvents[count];
var logoutEvent = computer.LogoutEvents[count];
sessionPairs.Add( new Sessons
{
DepartmentId = computer.DepartmentId,
DepartmentName = computer.DepartmentName,
ComputerId = computer.ComputerId,
ComputerName = computer.ComputerName,
LoginTime = loginEvent.EventDateTime,
LogoutTime = logoutEvent.EventDateTime,
UserId = loginEvent.UserId,
UserName = loginEvent.UserName,
Difference = logoutEvent.EventDateTime - loginEvent.EventDateTime
}
}
}
Это делает итерацию по запросу, затем по событиям входа в систему и выхода из системы, предполагая, что они правильно спарены.Скорее всего, вам нужно быть более избирательным в отношении того, как вы рассматриваете события, а не полагаться на цикл for.
SessionPairs будет List<Sessions>
и может быть сгруппирован по DepartmentID, чтобы получить набормероприятий по отделам.