NET Core 3.1: update a field of an entity when is inserting and updating

I am creating a REST API in NET Core 3.1. I have a table called GrRefBancos with columns to audit who and when insert or updated registers. How can I fill these columns automatically without having to send the values when an insert or update happens?

This is my code:

public abstract class BaseEntity
{
    public long Id { get; set; }
    public DateTime CreadoEl { get; set; }
    public string CreadoPor { get; set; }
    public DateTime? ActualizaEl { get; set; }
    public string ActualizaPor { get; set; }
    public DateTime? InactivaEl { get; set; }
}

public partial class GrRefBancos : BaseEntity
{
    public GrRefBancos()
    {
        IcFacturas = new HashSet<IcFacturas>();
        PrFacturas = new HashSet<PrFacturas>();
    }

    public string CodigoBanco { get; set; }
    public string Descripcion { get; set; }

    public virtual ICollection<IcFacturas> IcFacturas { get; set; }
    public virtual ICollection<PrFacturas> PrFacturas { get; set; }
}

In the DbContext, I tried with HasDefaultValue() function to insert, but it didn’t work:
modelBuilder.Entity<GrRefBancos>(entity =>
            {
                entity.HasKey(e => e.Id)
                    .HasName("PK_grrefbancos")
                    .IsClustered(false);

                entity.Property(e => e.ActualizaEl).HasColumnType("datetime");

                entity.Property(e => e.ActualizaPor)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.CodigoBanco)
                    .IsRequired()
                    .HasMaxLength(10)
                    .IsUnicode(false);

                entity.Property(e => e.CreadoEl)
                    .HasColumnType("datetime")
                    .HasDefaultValue(DateTime.Now);

                entity.Property(e => e.CreadoPor)
                    .IsRequired()
                    .HasMaxLength(50)
                    .HasDefaultValue("LoogedUser")
                    .IsUnicode(false);

                entity.Property(e => e.Descripcion)
                    .HasMaxLength(100)
                    .IsUnicode(false);

                entity.Property(e => e.InactivaEl)
                    .HasColumnName("InactivaEL")
                    .HasColumnType("datetime");
            });

Thanks for your attention.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You will need to override SaveChanges() or SaveChangesAsync(). Then, you’ll need to grab ChangeTracker and ask it for all entity entries by changeTracker.Entries().

Iterate over the collection returned, check Entry.State to see whether it is an insertion or an update and modify the auditing columns accordingly.

Your DbContext will need to be aware of the user who is performing the operation, however that is easy to take care of through clever use of DI. If DI is not possible due to circular dependencies, then raise an event from the SaveChanges[Async]() override above and ask for user name.

P.S.: You can decide to not make them part of your model by making the auditing columns shadow EF properties.

Method 2

With a trigger on the tables. And defining them as Computed in the EfCore meta model so Ef does not try to update them.

This will not work, though, because under a sane modern setup with connection pooling the database has no idea who the user actually is. The date / timestamp is “simple” – the user name is simply not available on the backend.

Method 3

You can implement this feature in your BaseRepository Class

class BaseRepository<T>{
     private readonly DbContext _dbContext;
     public BaseRepository(DbContext dbContext){
           _dbContext = dbContext;
     }
     public Update(T Entity, UserEntity userEntity){
            //Do anything you like here
     }
     public Insert(T Entity, UserEntity userEntity){
            //Do anything you like here
     }
}

and use it like this
_unitOfWork.GetRepository<MyRepository>().Update(MyEntity,UserEntity);
//or
_unitOfWork.GetRepository<MyRepository>().Insert(MyEntity,UserEntity);

You can Implement your Services to do it automatically maybe pass the HttpContext.User!
_myEntityService.Update(myDto,HttpContext.User);
//or
_myEntityService.Insert(myDto,HttpContext.User);

It is defiantly possible and the technical implementation totally depends on what you are really trying to achieve.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x