Entity Framework - DbContext

DbContext is the most important part of Entity Framework. There are many articles on Entity Framework and very small information on DbContext in a single place. In this article, I am trying to explain all aspects of DbContext and why it is the most important class in Entity Framework. 

What is DbContext?

The simple answer to this question DbContext is the CLASS in Entity Framework/Core.

As per Microsoft “A DbContext instance represents a session with the database and can be used to query and save instances of your entities. DbContext is a combination of the Unit Of Work and Repository patterns.” In simplified way we can say that DbContext is the bridge between Entity Framework and Database. Whatever we are doing in Entity Framework (get data, save data, fetch data or any other opration) is done via DbContext. 

What we can do with DbContext?

This is the next question. I am trying to answer or discuss one by one now. 

Manage database connection

As we know Entity Framework is build upon ADO.NET so EF also manage a Connection Pool. DbContext open the connection whenever needed at the time of communication with Database. Many times multiple operation done by single connection and vice versa. As it is managing the Connection pool we need not to worry about the connections. This is the beauty of entity Framework. 

Configure model & relationship

Basically Model is a class that represent database table, stored procedure, function and so on. We can create manually this class and configure it in DbContext like below or we can create all models of all or specific objects from Database.

public class Post  
{  
        public int PostId { get; set; }  
        public string Url { get; set; }  
}  
  
//Mention it in DbContext class like below  
public DbSet< Post > Posts { get; set; }  
  
//Configure model like below   
protected override void OnModelCreating(ModelBuilder modelBuilder)  
{  
        modelBuilder.Entity<Post>() .Property(b => b.Url) .IsRequired();  
}  
//Or we can use data annotation like below. [Required] in this case   
public class Post  
{  
        public int PostId { get; set; }  
  
        [Required]  
        public string Url { get; set; }  
}  

Query the database

Another advantage or feature of DBContext is we can query database using different approaches like using entities, stored procedures or even executing queries directly. few examples are as below 

  • Using entity - Here we can use single model for crud operation. if we need data of few columns from multiple tables, we can fetch as below 
    objData = (from c in context.TblDiscussion
              join ct in context.TblCallTypes on c.CallType equals ct.Id
              join cld in context.LoginDetails on c.AddedBy equals cld.LoginId
              where c.GroupId == GroupId
              select new DiscussionDetails
               {
                 Id = c.Id,
                 AddedDate = c.AddedDate,
                 SpokenTo = c.SpokenTo,
                 ContactNo = c.ContactNo,
                 CallType = ct.CallType,
                 CustomerType = c.CustomerType,
                 FollowupDate = c.FollowupDate,                                   
                 AddedBy = cld.UserName,
                 Status = c.Status,
                                      
                }).OrderByDescending(x => x.AddedDate).ToList();
  • Using Stored Procedure - With this approach we can call stored procedure and get data. if selecting data in SP we can get the data in model or list of model like below 
    List<ForGraph> lstData = new List<ForGraph>();
    
      using (var context = new CommonDBContext())
      {
          lstData = context.Database.SqlQuery<ForGraph>("sp_GetDataForGraph @type, @CSMember",
                    new SqlParameter("@type", type),
                    new SqlParameter("@CSMember", CSMember)).ToList<ForGraph>();
    
      }
  • Execute normal query - We can execute query directly. 
    using (var contextdb = new CommonDBContext(connStr))
    {                            
    
       var sqlQ = $"SELECT COUNT(*) as Count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TableName'";
       var exist = contextdb.Database.SqlQuery<int>(sqlQ).FirstOrDefault();
    }

Tracking changes

This is the most important feature of DBContext. we can track changes when we use for all type of operations or execution. 

using (var context = new CommonDBEntities()) {

   //Below line enable tracking for all operation inside this block, as object context gets disposed 
   context.Configuration.AutoDetectChangesEnabled = true;

   var student = (from stud in context.tblStudents where stud.Name == 
            "Dinesh" select stud).FirstOrDefault<Student>();

   //here we can check how many entities get affected
    context.ChangeTracker.Entries().Count();

   //If you want to check each entity that gets affected you can use below code
   var affectedEntities = context.ChangeTracker.Entries();

         foreach (var entity in affectedEntities) {
            // Here we can get name of entity
            Console.WriteLine("Affected Entity Name: {0}", entity.Entity.GetType().Name);
            
            // Here we can check state
            Console.WriteLine("Status Affected: {0}", entity.State);
         }

}

Managing Transaction

Transaction is very useful feature while working with Database(specially Relational Databases). When data gets inserted in multiple tables on single event the Transaction plays critical role to avoid data discrepancy. DBContext use transactions internally for individual operation and exactly it is the problem when we insert or update or delete data in multiple database tables. In these cases we can use Transaction explecitely as below 

using (var context = new CommonDBContext())
{
     using (DbContextTransaction transaction = context.Database.BeginTransaction())
     {
         try
         {
              context.tblStudents.AddOrUpdate(objStudent);
              context.SaveChanges();

              context.tblStudentsSalaryDetails.AddOrUpdate(objStudentSalary);
              context.SaveChanges();

              context.tblStudentsFamilyDetails.AddOrUpdate(objStudentFamily);
              context.SaveChanges();

              transaction.Commit();
         }
         catch (Exception ex)
         {
            transaction.Rollback();
            //Log Exception
         }
     }
}

In above code if all Insert/Update statements executed correctly without error the transaction gets commited and all data gets stored/updated successfully. if not means if any error occurs in any statement all inserted or updated data gets rollback. This way we can use transaction to avoid data discrepancy

__Happy Coding__


Similar Articles
Logiciel Softtech Pvt. Ltd.
We help you transform your business ideas with custom products, migrate from legacy applications.