Как извлечь контрольный журнал из двух таблиц SQL Server и вернуть их в правильном порядке? - PullRequest
3 голосов
/ 08 апреля 2011

Фоновый контекст:


У меня есть таблица базы данных с именем Project и таблица с именем ProjectHistory с той же схемой.Я использую nhibernate, поэтому у меня также есть объект домена с именем Project и объект домена с именем ProjectHistory (который получен из Project ).

Цель


Моя цель состоит в том, чтобы извлечь данные из этих таблиц и упорядочить их по порядку, когда произошедшие события и код C # выводят типичный экран контрольного журнала с последним n числом изменений

Подробности


Обе таблицы имеют следующие поля и типы данных
  • Id - (int) - первичный ключ в Project,ПРИМЕЧАНИЕ: в таблице истории нет PK
  • LastUpdated (datetime)
  • Имя (varchar)
  • Описание (varchar)
  • Отметка времени (отметка времени))

цель таблицы Projecthistory состоит в том, чтобы при каждом обновлении таблицы Project таблица ProjectHistory получалавставил новую строку со старой записью, чтобы я мог получить полный контрольный журнал.

Я сделалЕсли это с помощью этого триггера:

 ALTER TRIGGER ProjectTrigger
 ON Project
 AFTER UPDATE
 AS
    SET NOCOUNT ON

    insert into ProjectHistory
    select * from deleted

Моя проблема в том, что теперь мне нужен код C #, чтобы собрать историю аудита, где пользователь выбирает самое последнее n событий.

Пример:


Вот пример событий:
  1. 10 января - создание проекта 1 (пока ничего в истории)
  2. 11 января -создать проект 2
  3. 15 января - отредактировать проект 2 (поместит запись в таблицу истории проекта 2 с датой 11 января в последнюю очередь)
  4. 25 января - отредактировать проект 1 (поместитзапись в таблице истории проекта 1 с датой 10 января)

так что, как вы можете видеть, если я сортировал по убыванию по последнему обновленному полю в таблице истории, был помещен результатсобытие 4 перед результатом из события 3, которое вышло из строя.

код


Я попытался следующий код, чтобы попытаться поставить ихвместе, но я объясню недостаток ниже:

   public IEnumerable<Project> GetHistory<Project, ProjectHistory>(int numberOfChanges)
    {
        IEnumerable<Project> current;
        IEnumerable<Project> history;
            current = Session.Query<Project>()
                .OrderByDescending(r => r.LastUpdated)
                .Take(numberOfChanges);

             history = Session.Query<ProjectHistory>()
            .OrderByDescending(r => r.LastUpdated).Cast<Project>();

            IEnumerable<Project> all = current.Concat(history);
            return all.OrderByDescending(r => r.Id).ThenByDescending(r => r.LastUpdated);
        }
    } 

Мои основные проблемы с вышеупомянутой трескойЭто:

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

    1. Я мог бы использовать поле timestamp для сортировки (поскольку это было фактическое время, когда была введена запись), но не похоже, что вы можете сортировать по этому полю, используяC # nhibernate, потому что это поле просто двоичное (8), поэтому оно преобразуется в байт [] в C #, который не поддерживает IComparable.
  2. Я могу использовать Поле lastUpdated в таблице Project, поскольку сортировка по полю lastupdate приведет меня к последним событиям в порядке.Я думал о циклическом прохождении только таблицы project , а затем делал отдельный запрос для каждого проекта, чтобы получить последний исторический проект, но для них это не поддерживает случай, когда произошли множественные изменения одного и того же идентификатора проекта.Проблема в том, что я не могу найти способ получить данные в правильном порядке.

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

У меня уже есть код, который может сравнивать один Project объект с другим project объектом и возвращать поля diff (что отлично работает), но мне просто нужно предложение по выяснению, как яполучить эти данные из базы данных по этим таблицам в правильном порядке (либо из моего запроса, либо по коду после факта), чтобы я мог показать «последние n чисел изменений», а затем использовать свою логику, чтобы показатьполе diff для каждого из этих изменений.

Ответы [ 3 ]

0 голосов
/ 27 ноября 2012

Если я правильно понял ваш вопрос, вы можете просто отсортировать метку времени, преобразованную в long.

// The last row in your question, 0 means start from the start of byte[]
return all.OrderByDescending(r => BitConverter.ToInt64(r.Timestamp,0));
0 голосов
/ 29 ноября 2012

Вариант 1 : Вот ссылка , которая позволяет использовать метку времени в предложении order by. Я сам этим не пользовался, поэтому пользуйтесь на свой страх и риск.

Вариант 2 : Добавьте поле автоматического увеличения в ProjectHistory, а затем вы можете отсортировать результаты по идентификатору проекта, а затем по идентификатору автоматического увеличения. Я не очень часто использовал операцию приведения, поэтому я не уверен в этих последствиях, но я уверен, что у вас будет больше работы с отображением.

Вариант 3 : Вы исследовали NHibernate Envers , который является основой для поддержки и аудита? Это будет новая кривая обучения, но это может сэкономить вам много работы в долгосрочной перспективе.

0 голосов
/ 08 апреля 2011

Вот мое решение для одного подобного проекта.Создайте представление для объединения проекта и таблицы истории проекта.Позвольте серверу SQL сделать тяжелую работу.

Вот пример:

CREATE view [dbo].[VwProjectHistory] as select
    OtherFieldName,
    LastUpdated
from
    [dbo].[Project]

union all

select
    OtherFieldName,
    LastUpdated
from
    [dbo].[ProjectHistory]
...