I am working on a c# console application , and i am using entity framework 5.0 as the data access layer with sql server. now i want to track the changes and save them inside a log table. so to do so i am initiating 2 DbContext objects one for the business data while the other for the log data, as follow:-
class Sync { static void Main(string[] args) { string syncResult = "Sync started"; Entities entities = new Entities();//for business data Entities entities2 = new Entities();//for logs try { //code goes here entities.SaveChanges(); } catch (Exception e) { syncResult = string.IsNullOrEmpty(e.Message) ? "Error" : e.Message; } entities.Dispose(); entities2.LogHistories.Add(new LogHistory() { Description = syncResult }); entities2.SaveChanges(); entities2.Dispose();
now i provided separate DbContext objects for my logs , for the following reason/s:-
- if my first entity object is not able to save the changes , due to any reason such as unhandled validation error, or trying to hack the system, etc.. then the second entities2 will still be able to save the log entry. let take this example. let say i am integrating with a 3rd part API and i am expecting them to return JSON in a specific format.. now let assume that the return json object had missing data, in this case when i try adding the object it will raise and exception ... now since i am having separate entity object for the logs then the log entry will be saved (will not be affected by any business data exception). but if i was having a single DBContext object then the log entry will fail to save since i am unable to save the business data .. so my question is if initiating 2 DBContext objects one for logs and the other for business data a valid approach to follow, or it is a bad decision to follow?
Thanks
4 Answers
Answers 1
Don't use 2 contexts, you should use a logger (for example log4net with AdoNetAppender). As Evk points out in the comment down below, EF automatically wraps everything up into a transaction when you call SaveChanges()
, so as soon as an error occurs, nothing will be committed to the database and you can log the error. For example:
static void Main(string[] args) { ILog log = LogManager.GetLogger("Entities"); using(var ctx = new Entities()) { try { ... ctx.SaveChanges(); } catch(Exception ex) { log.Error(ex.Message); } } }
This way your application stays clean, you will only update when everything succeeds when you call SaveChanges()
at the end of the using
block, and only log when an exception happens. Also it's better with the using blocks to always dispose of your context, even if an unexpected exception would occur. The logger will take care of writing the errors to the database in another thread without slowing down your program. Perhaps you can try out NLog, I've heard it's better (= easier to configure/use) than log4net but I still have to give it a try myself.
Answers 2
Having multiple contexts for a single database can be useful if your database contains multiple database schemas and you want to handle each of them as a separate self contained area. Its not clear from your code / requirement if this is the case.
If the tables you are working with are in the same database & same schema, then I can't see a reason for you to use two DbContexts. Even if you have a validation error or exception, you can still save to your log table with the same context.
If you are trying to log errors and / or other relevant information, why not use log4net to do your logging?
EDIT
In my opinion, logging should be independent of your normal transactions so you don't have to think about this scenario. That being said, in a transaction you can save and log, but also log if there is an exception. Unless I'm missing something, I still don't see the need for 2 DBContexts.
Take a look at the following for some guidance around transactions.
Answers 3
There are some problems.
We keep running, if we face with exception on data entry (it can be, if any state isn't affected). But if we get exception at logging we don't handle ?
What our business logic is doing ? If we get wrong json data our business logic should check and handle it.
Ok let's say json is valid, it passes business logic. We have string field on db with varchar(20) but the data has 25 characters. So what our model validation is doing ?
You should handle these things on upper levels.
It's violate Single Responsibility. This method should have just one responsiblity which is saving entity to db. It shouldn't be responsible for logging also. You should implement it at another class.
Because of this, your problem occurs. You try to give two reponsibilities to the method. Then you try to choose 1 dbcontext or 2 dbcontexts I need. If you follow Single Responsibility this problem wouldn't occur.
You should implement a logger service. Your classes shouldn't know or care how logger service handles it. You can save it to db, file or cloud like loggly. Additionally your logger service shouldn't share same context with other classses.
Answers 4
Entity Framework 5 code first migrations is only able to manage a single DbContext per physical database instance. Entity Framework 6 code first migrations is able to manage multiple DbContext per physical database instance.
Check out pretty nice example at:
0 comments:
Post a Comment