1

I have an interface that many of my code-first entities implement:

public interface IRecordTracking
{
    DateTime CreateDate { get;set; }
    DateTime UpdateDate { get;set; }
} 

I also have a repository sitting in front of my DbContext with Add / Update methods with the following code:

Add:

if (item is IRecordTracking tracking)
    tracking.CreateDate = DateTime.UtcNow;

Update:

if (item is IRecordTracking tracking)
    tracking.UpdateDate = DateTime.UtcNow;

My problem is, I'm finding a scenario where I'm creating a whole chain of entities:

  • Sponsor
    • SponsorID
    • ...
    • EntityID
    • Entity
      • EntityID
      • Addresses
      • ...
      • CreateDate
      • UpdateDate

As you can see, the update/create is on the child property Entity.

When I call Add or Update on my repository, I'm passing the Sponsor object, but not the entity (except as a child property). So my check if "item is IRecordTracking" is false.

My question(s) are:

  • Is it possible on the DbContext to intercept all inserts/updates and run this logic there?
  • Or, is there a clean/efficient(ish) way of walking up the property tree and checking for types that implement IRecordTracking? This way, my repository (RepositoryBase classs) keeps the logic for this, but it checks all children...

Thanks

Adam Plocher
  • 13,994
  • 6
  • 46
  • 79
  • 3
    In the DbContext class you override the base OnSaveChange method. Most "EF Audit" projects do it this way. Eg https://www.meziantou.net/2017/08/14/entity-framework-core-history-audit-table – Jeremy Thompson Jul 29 '18 at 08:59
  • 1
    You can do this in an override of `SaveChanges`. You should be able to find examles of that. But I always prefer database triggers to do this kind of stuff. – Gert Arnold Jul 29 '18 at 09:00
  • 1
    @Gert has a point, all the engineering firms I've worked for had History tables, other firms were ok with CreatedBy, CreatedDate, ModifiedBy, ModifiedDate fields. And doing this in the db is more efficient, bit more overhead. I like the middle ground of recording only fields that have changed in one generic method. – Jeremy Thompson Jul 29 '18 at 09:17
  • Thanks guys, one detail I forgot to mention is that I'm also logging CreatedBy and UpdatedBy user IDs. I suppose that's an insignificant detail - not like the 4 fields MUST be glued together or anything. I will probably stick with the SaveChanges override for now, but this is a new app we're architecting and very soon we will be on a sprint that will include the audit logging. I may reconsider how this is implemented at that time (and utilize triggers as you suggested). Thanks again. I'll be happy to mark an answer if either of you guys post one. – Adam Plocher Jul 29 '18 at 11:25

1 Answers1

0

In the DbContext class you override the base OnSaveChange method's. Most "EF Audit" projects do it this way, and I'm an advocate, eg in .net core:

https://www.meziantou.net/2017/08/14/entity-framework-core-history-audit-table

@Gert has a point, all the engineering firms I've worked for had History tables, other firms were ok with CreatedBy, CreatedDate, ModifiedBy, ModifiedDate fields.

There's heaps on the topic depending on your dB, eg  How to store historical records in a history table in SQL Server

Gerts other point about doing it in the db is more efficient, however it is a bit more overhead. I like the middle ground of recording only fields that have changed in one generic method.

And if you can cloud enable that you're on right track.

Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321