Расширение базового типа и автоматическое обновление информации аудита на объекте - PullRequest
2 голосов
/ 07 апреля 2010

У меня есть модель сущности, в которой имеется информация аудита для каждой таблицы (более 50 таблиц)

 CreateDate
 CreateUser
 UpdateDate
 UpdateUser

В настоящее время мы программно обновляем информацию аудита.

Пример:

  if(changed){
        entity.UpdatedOn = DateTime.Now;
        entity.UpdatedBy = Environment.UserName;
        context.SaveChanges();
   }

Но я ищу более автоматизированное решение. Во время сохранения изменений, если объект создается / обновляется, я хотел бы автоматически обновить эти поля перед отправкой их в базу данных для хранения.

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

Было предложено решение переопределить SaveChanges и сделать это там, но для достижения этого мне либо пришлось бы использовать отражение (в котором я этого не хочу), либо получить базовый класс. Предполагая, что я пойду по этому маршруту, как бы я достиг этого?

Например

EXAMPLE_DB_TABLE
 CODE
 NAME
 --Audit Tables
 CREATE_DATE
 CREATE_USER
 UPDATE_DATE
 UPDATE_USER

А если я создам базовый класс

 public abstract class IUpdatable{

     public virtual DateTime CreateDate {set;}
     public virtual string CreateUser { set;}
     public virtual DateTime UpdateDate { set;}
     public virtual string UpdateUser { set;}
 }

Конечная цель - сделать что-то вроде ...

   public overrride void SaveChanges(){
        //Go through state manager and update audit infromation
        //FOREACH changed entity in state manager
        if(entity is IUpdatable){
           //If state is created... update create audit.
           //if state is updated... update update audit
        }
   }

Но я не уверен, как мне поступить с генерацией кода, который расширил бы интерфейс.

Ответы [ 4 ]

1 голос
/ 19 апреля 2010

Здесь было окончательное решение.

Я в основном проверяю свою модель на наличие 4 свойств. Если объект содержит

InsertedOn и InsertedBy и updatedOn и updatedBy Я генерирую (используя файл tt) следующую сущность, которая реализует интерфейс IAuditable.

public interface IAuditable
{
    void SetInsertedOn(DateTime date);
    void SetInsertedBy(string user);
    void SetUpdatedOn(DateTime date);
    void SetUpdatedBy(string user);
}

public partial class ExampleDBtable: EntityObject, Audit.IAuditable
{
     //Normal EDMX stuff here..
     public static ExampleDBtable CreateExampleDBtable(int id, string code, string name, DateTime insertedOn, string insertedBy, DateTime updatedOn, string updatedBy)
       {

       }
       //Extension points.
    #region IAuditable Members

    public void SetInsertedOn(DateTime date)
    {
        this._InsertedOn = date;
    }

    public void SetInsertedBy(string user)
    {
        this._InsertedBy = user;
    }

    public void SetUpdatedOn(DateTime date)
    {
        this._UpdatedOn = date;
    }

    public void SetUpdatedBy(string user)
    {
        this._UpdatedBy = user;
    }

    #endregion

    }

Я также генерирую код для обновления информации аудита

   public ExampleDBObjectContext(string connectionString) : base(connectionString, "publicExampleDBObjectContext")
    {
        this.SavingChanges += new EventHandler(UpdateAuditInformation);
        this.OnContextCreated();
     }

И, наконец, я реализовал UpdateAuditInformation

   foreach (ObjectStateEntry entry in
            context.ObjectStateManager.GetObjectStateEntries(
            EntityState.Added | EntityState.Modified))
        {
              //Start pseudo code..
              if(entry.Entity is IAuditable){
                 IAuditable temp = entry.Entity as IAuditable;
                 temp.SetInsertedOn(DateTime.Now);
                 temp.SetInsertedBy(Env.GetUser());
                 ...

              }
        }

Я решил не показывать файл .tt, потому что он выглядит ужасно в редакторе.

0 голосов
/ 13 апреля 2010

Посмотрите на PostSharp . Очень хорошее решение для таких задач.

0 голосов
/ 13 апреля 2010

Не проще ли «помечать» обновленные строки с помощью триггеров базы данных?Достаточно ли адекватна информация, представленная в базе данных?(пользователь базы данных и пользователь ОС)

0 голосов
/ 07 апреля 2010

Да, я думаю, вы можете сделать что-то подобное. Общая идея будет

  1. Дескриптор ObjectContext.SavingChanges .
  2. В этом случае вызовите ObjectContext.ObjectStateManager.GetObjectStateEntries (EntityState.Modified)
  3. Повторяйте результаты и устанавливайте свойства, если это необходимо.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...