Overriding Savechanges and Setting Modifieddate, But How to Set Modifiedby

Overriding SaveChanges and setting ModifiedDate, but how do I set ModifiedBy?

You can use the HttpContext.Current.User.Identity.Name to get the name of the current user.

public override int SaveChanges()
{
var changeSet = ChangeTracker.Entries<IAuditable>();

if (changeSet != null)
{
foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged))
{
entry.Entity.ModifiedDate = DateProvider.GetCurrentDate();
entry.Entity.ModifiedBy = HttpContext.Current.User.Identity.Name;
}
}
return base.SaveChanges();
}

Better way to do this would be to use constructor injection to pass the current user to the context

public class MyContext : DbContext
{
public MyContext(string userName)
{
UserName = userName;
}

public string UserName
{
get; private set;
}

public override int SaveChanges()
{
var changeSet = ChangeTracker.Entries<IAuditable>();

if (changeSet != null)
{
foreach (var entry in changeSet.Where(c => c.State != EntityState.Unchanged))
{
entry.Entity.ModifiedDate = DateProvider.GetCurrentDate();
entry.Entity.ModifiedBy = UserName;
}
}
return base.SaveChanges();
}
}

Set Last Updated on each SaveChanges in Entity

Here is how you can do it by overriding SaveChanges method:

public override int SaveChanges()
{
IEnumerable<DbEntityEntry<BaseEntity>> entries = ChangeTracker.Entries<BaseEntity>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);

foreach (DbEntityEntry<BaseEntity> entry in entries)
{
entry.Entity.LastUpdated = DateTime.Now;
}

return base.SaveChanges();
}

Best way to override SaveChanges()

you can do the following

1- create an Interface in your application that all the classes that has the following properties will implement this interface: Id, CreatedDate,CreatedBy, ModifiedDate,ModifiedBy

public interface ITrack
{
int Id{get; set;}
int CreatedBy{get; set;}
DateTime CreatedDate{get; set;}
int? ModifiedBy{get; set;} // int? because at first add, there is no modification
DateTime? ModifiedBy {get; set;}
}

Best practices Define the CreatedBy and ModifiedBy as string which will be good for performance and maintenance

2- Add a class TrackableEntry which implements the interface ITrack

public abstract class TrackableEntry : ITrack
{
public int Id{get; set;}
public int CreatedBy{get; set;}
public DateTime CreatedDate{get; set;}
public int? ModifiedBy{get; set;}
public DateTime? ModifiedBy {get; set;}
}

3- remove the properties mentioned in the interface from all of your classes and let these classes to implement directly from TrackableEntry

public class A: TrackableEntry
{
//public int Id{get; set;}
//public int CreatedBy{get; set;}
//public DateTime CreatedDate{get; set;}
//public int? ModifiedBy{get; set;}
//public DateTime? ModifiedBy {get; set;}
}

4- In your DbContext file override your SaveChanges and add property UserId or UserName if you followed the *Best practices* part

public int UserId{get; set;}

public override int SaveChanges()
{
this.ChangeTracker.DetectChanges();
var added = this.ChangeTracker.Entries()
.Where(t => t.State == EntityState.Added)
.Select(t => t.Entity)
.ToArray();

foreach (var entity in added)
{
if (entity is ITrack)
{
var track = entity as ITrack;
track.CreatedDate = DateTime.Now;
track.CreatedBy = UserId;
}
}

var modified = this.ChangeTracker.Entries()
.Where(t => t.State == EntityState.Modified)
.Select(t => t.Entity)
.ToArray();

foreach (var entity in modified)
{
if (entity is ITrack)
{
var track = entity as ITrack;
track.ModifiedDate = DateTime.Now;
track.ModifiedBy = UserId;
}
}
return base.SaveChanges();
}

finally in your forms when you want to call SaveChanges method, ensure you set the UserId or UserName value

var entities=new Entities(); // assuming that your DbContext file called Entities
// code for adding or deletion or modification here
entities.As.Add(new A(){...});

// ....

entities.UserId=MyUser;
entities.SaveChanges();

hope this will help you

How do I add a new record to objectStateEntryList in SaveChanges override

EF by default will use both - it uses original values to check for a concurrency issue (i.e. if the record has changed since you loaded the data from the DB) then uses the entity's current/modified values to update the DB record.

It is not possible to have EF "detect and handle these entities automatically". You will need to create a new instance of the entity object, copy the values from the existing entity object, set the appropriate effective and expired dates on both objects, add the new entity object to the DbContext, then save changes. The best place to do this is by overriding the SaveChanges() method of your DbContext. To keep it as clean and manageable as possible, I suggest using the repository pattern.

How to correctly override the SaveChanges function in EF 4.1

You can override in your context class,

public partial class YourDbContext: DbContext
{
public YourDbContext()
{
}
public override int SaveChanges()
{
// do your additional stuff here.. (Ex:- save current user)
return base.SaveChanges();
}
}

And the other option is you can set default values in the constructor of your entity,

   Public class YourEntity{

public YourEntity(){
CreatedDate=DateTime.Now;
}

Public DateTime CreatedDate{get;set;}
}

Entity Framework 7 SaveChanges

ChangeTracker.Entries() allows you to get all of the entity changes. You could override SaveChanges in your DbContext and set the modified properties using something like the following code.

public override int SaveChanges()
{
SetModifiedInformation();
return base.SaveChanges();
}

public override async Task<int> SaveChangesAsync( CancellationToken cancellationToken = new CancellationToken() )
{
SetModifiedInformation();
return await base.SaveChangesAsync( cancellationToken );
}

private void SetModifiedInformation()
{
foreach (var entityEntry in ChangeTracker.Entries())
{
var entity = entityEntry.Entity as ChangeTracking;
if (entity != null)
{
entity.ModifiedBy = "Get User Here";
entity.ModifiedTime = DateTime.Now;
}
}
}


Related Topics



Leave a reply



Submit