Entity Framework – Atribuir valores antes dos dados serem salvos

Olá,

Um cenário bastante comum, que encontro nos fóruns, é a necessidade de registrar alguma informação na entidade antes dela ser salva na base de dados, via Entity Framework.

Dados como: “data de inclusão”, “data da última atualização”, “registro de log”, “usuário que realizou a alteração” e outros, são dados pertinentes para o funcionamento da aplicação e que estão atrelados ao evento de inclusão e atualização dos dados na base de dados.

duck9ph

Vamos propor um exemplo: supondo que temos de gravar documentos em nossa base de dados e temos de registrar informações sobre a data de inclusão e data da última alteração do documento.

Propomos então que a estrutura de nossa classe de documentos tem a seguinte estrutura:

public class Document
{
    public int Id { get; set; }

    public string Title { get; set; }

    public DateTime CreationTime { get; set; }

    public DateTime LastUpdate { get; set; }

    public byte[] Content { get; set; }
}

E nossa classe de contexto com o banco de dados contém o seguinte código:

public class DataContext : DbContext
{
    public DbSet<Document> Documents { get; set; }

    public DataContext()
    {
        Database.SetInitializer<DataContext>(new DropCreateDatabaseIfModelChanges<DataContext>());
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add<Document>(new DocumentConfiguration());

        base.OnModelCreating(modelBuilder);
    }

    public override int SaveChanges()
    {   
        // Detecta as alterações efetuadas sobre as entidades
        this.ChangeTracker.DetectChanges();

        // Identifica as instâncias de 'Document' existentes 
        // dentro do ChangeTracker
        var documents = ChangeTracker.Entries<Document>();

        if (documents != null)
        {
            // Varre os 'Documents' existentes no ChangeTracker
            foreach (DbEntityEntry<Document> item in documents)
            {
                // Verifica o estado do item
                switch (item.State)
                {
                    case EntityState.Added:                           
                        item.Entity.LastUpdate = item.Entity.CreationTime = DateTime.Now;                             
                        break;
                    case EntityState.Modified:
                        item.Entity.LastUpdate = DateTime.Now;
                        break;
                }
            }
        }

        // Realiza a gravação dos itens na base de dados
        return base.SaveChanges();
    }
}

Notemos então que nossa classe de contexto com o banco de dados sobrescreve o método “SaveChanges()” e adiciona uma lógica própria para identificação de possíveis instâncias de documentos existentes no ChangeTracker. O ChangeTracker é um pool que acumula todas as instâncias que sofreram alguma alteração, seja ela uma inclusão, modificação ou exclusão.

Note que dentro desta lógica identificamos qual o estado de nossa instância (Added ou Modified) e atribuímos a data corrente as propriedades LastUpdate e CreationTime conforme necessário.

Para testar o funcionamento de nossa lógica, montei o bloco de código abaixo:

class Program
{
    static void Main(string[] args)
    {
        using (DataContext context = new DataContext())
        {
            Document newDocument = new Document();

            newDocument.Title = "Document 1";

            context.Documents.Add(newDocument);

            context.SaveChanges();

            newDocument.Title = "Document 1*";

            context.SaveChanges();

        }
    }
}

Este post foi bastante simples, mas responde a muitas dúvidas que surgem nos fóruns.

Espero que seja útil

Por

Msc. Fernando Henrique Inocêncio Borba Ferreira

Microsoft Most Valuable Professional – Data Platform Development

Anúncios

5 Responses to Entity Framework – Atribuir valores antes dos dados serem salvos

  1. Jone Polvora says:

    Muito bom. Ficaria melhor ainda se utilizar uma interface nas entidades, assim o SaveChanges verifica se a classe implementa a interface e entao aplica a atualizacao de data/hora, ao inves de escrever codigo para cada entidade.

  2. Yan Justino says:

    Parabéns pelo post, Fernando! Eu particularmente eu tenho uma entidade base onde fica minha chave primária e minhas propriedades de data de atualização e criação

    • Grande Yan!
      Sim! Usar classes base com os atributos básicos para cada entidade são uma vantagem dos ORMs.

      Outro ponto vantajoso é o uso de rotinas de log das entidades. Este é o ponto perfeito para a inclusão de lógicas deste tipo.

      []s e obrigado por postar!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: