Конвертируйте код структуры сущностей C # в raw SQL для повышения - PullRequest
0 голосов
/ 17 мая 2018

У меня есть требование, где мне нужно проверять логины и пары выхода из системы в таблице eventsLogs.Пара состоит из одного входа и одного выхода.В таблице eventLogs есть много событий, которые меня интересуют в eventType 11 и 12, что означает, когда пользователь вошел в систему (событие 11) и вышел из системы (событие 12).Для этого пользователя могут быть повторяющиеся события с компьютера.Например, login, login, logout, поэтому в C # я делаю первый вход в систему, а затем нахожу его пару.Проблема в том, что я не знаю, как это сделать в SQL, к сожалению, я загружаю все входы и выходы в память !.Я хочу способ, чтобы я мог вызвать процедуру хранилища и получить тот же результат, который я сейчас привязываю к классу в C #.Я буду очень признателен за вашу помощь.Если я плохо объяснил свой вопрос, пожалуйста, попросите объяснения.

 // C#
   var departmentEventsDic = new Dictionary<string, List<Sessions>>();   

   //get all departments and run the loop
 foreach (var department in departments)
                    {
                        // create a list to push a pairs
                        var sessionPairsList = new List<Sessions>();
                      // for each computer in the department
                        foreach (var computer in department.Computers)
                        {

                            var  tempLogs= eventLogs.Where(x => x.ComputerId == computer.ComputerId) .OrderBy(x => x.EventDateTime).ToList();
                            var tempUnlock = DateTime.MinValue;

                            //for each log for the computer 
                            foreach (var log in tempLogs)
                            {
                                // if the event is login store it in temp varible 
                                if (log.EventType == 11)
                                {
                                    tempUnlock = log.EventDateTime;

                                }
                                // if its logout and its time is greater than tempUnlock , found a pair create class and add to list 
                                if (log.EventType == 12 && (tempUnlock != DateTime.MinValue) && log.EventDateTime > tempUnlock)
                                {
                                    var sessionPair = new Sessions
                                    {
                                        DepartmentId = department.DepartmentId,
                                        DepartmentName = department.DepartmentName,
                                        ComputerId = computer.ComputerId,
                                        ComputerName = computer.Name,
                                        LoginTime = tempUnlock,
                                        LogOutTime = log.EventDateTime,
                                        UserId = department.Users.FirstOrDefault(x => x.UserId == log.UserId)?.UserId,
                                        UserName = department.Users.FirstOrDefault(x => x.UserId == log.UserId)?.Name,
                                        Difference = (log.EventDateTime - temUnlock)
                                    };
                                    sessionPairsList.Add(sessionPair);
                                }
                            }
                        }
                        // add to dictionary with department name as key and list of sessionspairs as values

                        departmentEventsDic.Add(department.DepartmentName, sessionPairsList);
                    }



 public class Results
    {
        public Guid DepartmentId { get; set; }
        public string DepartmentName { get; set; }
        public Guid ComputerId { get; set; }
        public string ComputerName { get; set; }
        public DateTime LoginTime { get; set; }
        public DateTime LogOutTime { get; set; }
        public Guid? UserId { get; set; }
        public string UserName { get; set; }
        public TimeSpan Difference { get; set; }
    }       
    //Tables
    CREATE TABLE [dbo].[Departments](
    [DepartmentId] [uniqueidentifier] NOT NULL PrimaryKey,
    [DepartmentName] [nvarchar](max) NULL
    );
    CREATE TABLE [dbo].[Computers](
    [ComputerId] [uniqueidentifier] NOT NULL PrimaryKey,    
    [DepartmentId] [uniqueidentifier] NOT NULL, 
    [Name] [nvarchar](max) NULL );

    ALTER TABLE [dbo].[Computers]  WITH CHECK ADD  CONSTRAINT [FK_Computers_Departments_DepartmentId] FOREIGN KEY([DepartmentId])
    REFERENCES [dbo].[Departments] ([DepartmentId])
    ON DELETE CASCADE



     CREATE TABLE [dbo].[EventLogs](
    [EventLogId] [uniqueidentifier] NOT NULL PrimaryKey,
    [ComputerId] [uniqueidentifier] NOT NULL,
    [EventDateTime] [datetime2](7) NOT NULL,
    [EventType] [int] NOT NULL,
    [UserId] [uniqueidentifier] NULL);
    ALTER TABLE [dbo].[EventLogs]  WITH CHECK ADD  CONSTRAINT [FK_EventLogs_Computers_ComputerId] FOREIGN KEY([ComputerId])
    REFERENCES [dbo].[Computers] ([ComputerId])
    ON DELETE CASCADE



   CREATE TABLE [dbo].[Users](
    [UserId] [uniqueidentifier] NOT NULL,
    [DepartmentId] [uniqueidentifier] NOT NULL, 
    [Name] [nvarchar](max) NULL);
    ALTER TABLE [dbo].[Users]  WITH CHECK ADD  CONSTRAINT [FK_Users_Departments_DepartmentId] FOREIGN KEY([DepartmentId])
    REFERENCES [dbo].[Departments] ([DepartmentId])
    ON DELETE CASCADE

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

В вашем заголовке указано, что вы хотите преобразовать это в код SQL.Это все выполнимо в TSQL, но сначала вам нужно знать синтаксис для преобразования кода C # в TSQL.Здесь я предоставляю все элементы, которые вам понадобятся, чтобы туда попасть.

Используйте процедуру создания с параметрами OUTPUT, если вам нужно вернуть значения обратно из хранимой процедуры.Все параметры в хранимой процедуре выглядят как @parameter с типом данных.

В TSQL нет оператора foreach, но вы можете заменить их на циклы while и вложить их, но вам нужно будет получить счетчикиз строк, которые вы собираетесь сначала проанализировать с помощью Select Count (*), сохраните его в переменной, а затем увеличивайте его каждый раз в цикле while.(ПРИМЕЧАНИЕ. Будьте осторожны с циклами while в хранимых процедурах SQL Server, они могут поставить сервер на колени, если у вас нет четкого пути выхода из цикла while.)

Ваши операторы lamda в C # будутнеобходимо преобразовать в серию операторов IF / Else или, возможно, в оператор CASE в TSQL.

Временные таблицы можно использовать в хранимых процедурах, присваивая имя таблицы с # перед именем, и это полезно для выброса значений в память и последующей манипулирования ими для получения желаемого результата.

Надеюсь, это даст вам еще несколько идей для решения хранимых процедур TSQL.

0 голосов
/ 17 мая 2018

Вы можете значительно оптимизировать подобные операции, используя 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, чтобы получить набормероприятий по отделам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...