Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automatically populate CreatedDate and ModifiedDate?

I am learning ASP.NET Core MVC and my model is

namespace Joukyuu.Models
{
    public class Passage
    {
        public int PassageId { get; set; }
        public string Contents { get; set; }


        public DateTime CreatedDate { get; set; }
        public DateTime ModifiedDate { get; set; }
    }
}

The Passage table is used to save passages I wrote.

Scenario

  • Create view just has one field Contents to input a passage. CreatedDate and ModifiedDate must be automatically set equal by the server (using UTC format).

  • Edit view just has one field Contents to edit a passage. ModifiedDate must be automatically set by the server.

Question

What attributes I have to attach to the CreatedDate and ModifiedDate properties to make them automatically populated by the server based on the above scenario?

like image 619
xport Avatar asked Jul 04 '16 10:07

xport


3 Answers

What attributes I have to attach to the CreatedDate and ModifiedDate properties to make them automatically populated by the server based on the above scenario?

Solution 1)

namespace Joukyuu.Models
{
    public class Passage
    {
        public int PassageId { get; set; }
        public string Contents { get; set; }


        public DateTime CreatedDate { get; set; }
        public DateTime ModifiedDate { get; set; }

       public Passage()
       {          
         this.CreatedDate  = DateTime.UtcNow;
         this.ModifiedDate = DateTime.UtcNow;
       }
    }
}

and by edit you have to change/update it by your self!

Solution 2)

Custom attribute:

[SqlDefaultValue(DefaultValue = "getutcdate()")]
public DateTime CreatedDate { get; set; }

Entity Framework 6 Code first Default value

Solution 3)

with help of Computed:

[Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedUtc { get; set; 


  "dbo.Products",
            c => new
                {
                    ProductId = c.Int(nullable: false, identity: true),
                    Name = c.String(),
                    CreatedUtc = c.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"),
                })
            .PrimaryKey(t => t.ProductId);

https://andy.mehalick.com/2014/02/06/ef6-adding-a-created-datetime-column-automatically-with-code-first-migrations/

Solution 4) You can also do this with command interceptor by modifying manually the query.

Solution 5) Use Repository pattern to manage the data creation and set it by CreateNew This is my favour Solution!

https://msdn.microsoft.com/en-us/library/ff649690.aspx

Solution 6) just set it or get in in the UI or in your VM.


In Entity Framework Core 1.0 easy:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Passage>()
        .Property(b => b.CreatedDate )
        .HasDefaultValueSql("getdate()");
}
like image 124
Bassam Alugili Avatar answered Nov 18 '22 00:11

Bassam Alugili


For those who are using the asynchronous system (SaveChangesAsync) and .NET Core, it's better to override the DbContext's SaveChangesAsync method:

public override Task<int> SaveChangesAsync(
    bool acceptAllChangesOnSuccess,
    CancellationToken cancellationToken = default(CancellationToken))
{
    var AddedEntities = ChangeTracker.Entries()
        .Where(E => E.State == EntityState.Added)
        .ToList();

    AddedEntities.ForEach(E =>
    {
        E.Property("CreationTime").CurrentValue = DateTime.Now;
    });

    var EditedEntities = ChangeTracker.Entries()
        .Where(E => E.State == EntityState.Modified)
        .ToList();

    EditedEntities.ForEach(E =>
    {
        E.Property("ModifiedDate").CurrentValue = DateTime.Now;
    });

    return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}

Also, you can define a base class or an interface for your models with these properties:

public class SaveConfig
{
    public DateTime CreationTime { get; set; }
    public DateTime? ModifiedDate { get; set; }
}
like image 39
Arash Avatar answered Nov 17 '22 23:11

Arash


If you are using Code first you could try this

[Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDate { get; set; }

On Migration

AddColumn("Passage", "CreatedDate", n => n.DateTime(nullable: false, defaultValueSql: "GETDATE()"));

More reference here,similar answer

Or you can global override the saveChanges Note* This will affect on the entire model if you have the CreatedDate field

public override int SaveChanges()
{
  DateTime saveTime = DateTime.Now;
  foreach (var entry in this.ChangeTracker.Entries()
      .Where(e => e.State == (EntityState) System.Data.EntityState.Added))
   {
     if (entry.Property("CreatedDate").CurrentValue == null)
       entry.Property("CreatedDate").CurrentValue = saveTime;
   }
   return base.SaveChanges();  
}
like image 10
Eldho Avatar answered Nov 17 '22 23:11

Eldho