0

I have an implementation of Entity Framework Core's DbContext class, MyTestDbContext.

Now I don't want other developers to call MyTestDbContext.SaveChanges() because I would like them to call an overload of it I created, MyTestDbContext.SaveChanges(string userName).

In case they call the MyTestDbContext.SaveChanges() method, I have overridden it to throw an exception, but how can I call the base.SaveChanges() from my new SaveChanges(string userName) method?

This code, when executing return base.SaveChanges(), calls the child method and throws the exception.

How can I avoid this and directly call its parent?

public class MyTestDbContext: DbContext {

   public override int SaveChanges()
   { 
      throw new Exception("Use SaveChanges(userName) instead");
   }

   public int SaveChanges(string userName)
   { 
      if (userName == "admin")
         return base.SaveChanges();
         else return 1;
   }
}
Callum Watkins
  • 2,844
  • 4
  • 29
  • 49
  • 2
    Have SaveChanges() call your overloaded version. You could pass null and then throw the exception from `SaveChanges(string userName)`, as you check the value of userName. – insane_developer Jan 19 '21 at 18:16
  • 1
    If you want to implement authorization and prevent unauthorized users from modifying the database, you're doing it wrong *and* introducing bugs. First of all, all databases have security features and permissions. If you don't user `root` or `sa` for all database connections, the best place to enforce security is in the database itself. Beyond that, [global query filters](https://learn.microsoft.com/en-us/ef/core/querying/filters) and/or [interceptors](https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/interceptors) can be used to filter, alter or abort operations. – Panagiotis Kanavos Jan 19 '21 at 18:22
  • Besides, nothing prevents other developers from calling `SaveChanges(name)`. If you want to prevent modifications you'll need to create [a read-only DbContext](https://stackoverflow.com/questions/10437058/how-to-make-entity-framework-data-context-readonly). Notice the answer: `In addition to connecting with a read-only user ...`. Someone could call `FromSqlRaw` after all – Panagiotis Kanavos Jan 19 '21 at 18:25
  • Panagiotis, but if instead of if(userName == "admin") I had a call to DB custom proc, developped by my organization. that returs if ihave permissions for edit. Would it be wrong from my c# side? – Gerardo Javier Gonzalez Brena Jan 19 '21 at 18:52
  • @GerardoJavierGonzalezBrena the point is that you shouldn't be doing it at the SaveChanges level. You should be doing it at the context level. This violates the "Principle of Least Astonishment". How would I, as a developer, know which version to call and why? By creating separate contexts, you leave a clear path in the code as to what to call and how to call it and you can then bind to different procs via the context. – David L Jan 19 '21 at 18:59
  • In addition to the practical problems already noted, your class violates the Liskov Substitution Principle. – StackOverthrow Jan 19 '21 at 19:03
  • But how can i do it at the context level, if i need to check if userName is "admin" just for saving – Gerardo Javier Gonzalez Brena Jan 19 '21 at 19:09
  • It sounds to me like you can implement roles and stop this at the very beginning. – insane_developer Jan 19 '21 at 20:36

0 Answers0