Smart overriding of the SaveChanges-Method of the EntityFramework

 

As part of our refactoring of the persistence layer implemented with the Entity Framework, we developed an approach for some tricky problems. Although i just discuss one specific scenario, the following solution is probably useful for many different issues:

We are using some objects which won’t be deleted in the classic way by removing them from the underlying database table. Instead, we mark them as deleted, set the purge date and the user who initiated the action. The same procedure exists for creating and modifing objects. You surely can imagine why we are doing this. So how can we achieve this behaviour in a transparent, implicit manner.

Step 1: Set up some interfaces like IHaveCreationDate, IHavePurgeDate and IHaveModificationDate.

   1: public interface IHavePurgeDate

   2: {

   3:     void SetPurgeDate();

   4: }

 

Step 2: Now it depends on your engineering strategy: Code First, Model First or Database First. According to your strategy you might using POCOs or you don’t. First of all, you can implement this solution in every single case, but you might change a little of the implementation. Here’s the way like we are using it with our POCOs (take a look at the ADO.NET Team Blog about the usage of POCOs) automatically generated by the EF:

Auto generated code:

   1: public partial class Worker

   2: {

   3:     public int ID_Bearbeiter { get; set; }

   4:     //some properties

   5:     public int deleted_from { get; set; }

   6:     public Nullable<System.DateTime> purge_date { get; set; }

   7:     public bool isDeleted { get; set; }

   8: }

 

Second part of the partial worker implementation in a separate file (don’t adapt the auto generated class!)

   1: public partial class worker : IHavePurgeDate 

   2: {

   3:     public void SetPurgeDate()

   4:     {

   5:         isDeleted = true;

   6:         purge_Date = DateTime.Now;

   7:         deleted_from = currentUser.ID;

   8:     }

   9: }

If you use Code First engineering, you won’t need a seperate file – of course!

 

Step 3: Build your own context or extend the existing one

If you use the auto generated context of the EF, you will have to create one more partial class to extend this context. If you use you’re own implementation, you can add the following code directly to your class:

   1: public override int SaveChanges()

   2: {

   3:     HandleEntries(ChangeTracker.Entries().ToList());

   4:     return base.SaveChanges();

   5: }

   6:  

   7: internal void HandleEntries(IList<DbEntityEntry> entries)

   8: {

   9:     HandleModifiedEntries(entries);

  10:  

  11:     HandleDeletedEntries(entries);

  12:  

  13:     HandleAddedEntries(entries);

  14: }

  15:  

  16: internal void HandleAddedEntries(IEnumerable<DbEntityEntry> entries)

  17: {

  18:     var createdEntities = entries

  19:         .Where(e => e.State == EntityState.Added)

  20:         .Where(e => e.Entity is IHaveCreationDate)

  21:         .ToList();

  22:  

  23:  

  24:     foreach (var dbEntityEntry in createdEntities)

  25:     {

  26:         ((IHaveCreationDate) dbEntityEntry.Entity).SetCreationDate();

  27:     }

  28: }

  29:  

  30: internal void HandleDeletedEntries(IEnumerable<DbEntityEntry> entries)

  31: {

  32:     var deletedEntities = entries

  33:         .Where(e => e.State == EntityState.Deleted)

  34:         .Where(e => e.Entity is IHavePurgeDate)

  35:         .ToList();

  36:  

  37:     foreach (var dbEntityEntry in deletedEntities)

  38:     {

  39:         ((IHavePurgeDate) dbEntityEntry.Entity).SetPurgeDate();

  40:         dbEntityEntry.State = EntityState.Modified;

  41:     }

  42: }

  43:  

  44: internal void HandleModifiedEntries(IEnumerable<DbEntityEntry> entries)

  45: {

  46:     var modifiedEntities = entries

  47:         .Where(e => e.State == EntityState.Modified)

  48:         .Where(e => e.Entity is IHaveModificationDate)

  49:         .ToList();

  50:  

  51:     foreach (var dbEntityEntry in modifiedEntities)

  52:     {

  53:         ((IHaveModificationDate) dbEntityEntry.Entity).SetModificationDate();

  54:     }

  55: }

 

That’s all. Be aware of two more things:

  • This code sample works with a DbContext of EF 4.1, but you can also use the ObjectStateManager of the ObjectContext in EF 1.0/4.0.
  • The order of handling modification and creating/deletion depends on your intended use.

Mit Tag(s) versehen:

One thought on “Smart overriding of the SaveChanges-Method of the EntityFramework

  1. […] Smart overriding of the SaveChanges-Method of the EntityFramework […]

    Gefällt mir

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: