Code-First Stored Procedure Entity Framework 6.0

Introduction

 
Code-First configures all entities to do the CRUD operations using direct table access. Using Entity Framework 6.0 and above, we can configure our code first model to use a Stored Procedure for a few or all entities of the model.
 

Stored Procedure Mapping

 
To use a Stored Procedure with the Code First model, we need to override the OnModelCreating method of DBContext and add the following code to map the Stored Procedure.
  1. protected override void OnModelCreating(DbModelBuilder modelBuilder)  
  2. {  
  3.     modelBuilder.Entity<yourEntity>().MapToStoredProcedures();  
  4. }  
The MapToStoreProcedures method has two overloaded methods, one method is without a parameter. This method uses Entity Framework code-first conventions to set up the Stored Procedure. Another method takes an action method as input and allows us to customize the Stored Procedure name, parameter, schema name, and so on.
 
By default an insert Stored Procedure has a parameter for every property except the properties marked as store generated (identity and computed). This Stored Procedure returns the value of the store generated column. An Update Stored Procedure has a parameter for every property except properties marked as a store generated (computed only). This Stored Procedure returns the result set with computed properties. Delete Stored Procedure has a parameter that is part of the entity key. This Stored Procedure returns nothing.
 
Example
 
I have the following classes:
  1. public class DepartmentMaster  
  2. {  
  3.     [Key]  
  4.     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
  5.     public int DepartmentId { getset; }  
  6.     public string Code { getset; }  
  7.     public string Name { getset; }  
  8.     public List<EmployeeMaster> Employees { getset; }  
  9. }  
  10.   
  11. public class EmployeeMaster  
  12. {  
  13.     [Key]  
  14.     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
  15.     public int EmployeeId { getset; }  
  16.     public string Code { getset; }  
  17.     public string Name { getset; }  
  18.     public int DepartmentId { getset; }  
  19.     public DepartmentMaster Department { getset; }  
  20. }  
My context class is as in the following. In this class, I overrode the OnModelCreating method to map the Stored Procedure with the EmployeeMaster entity.
  1. public class EntitiesContext : DbContext  
  2. {  
  3.     public EntitiesContext() base("name=Entities")  
  4.     {  
  5.   
  6.     }  
  7.  
  8.     public DbSet<DepartmentMaster> Departments { getset; }  
  9.     public DbSet<EmployeeMaster> Employees { getset; }  
  10.   
  11.     protected override void OnModelCreating(DbModelBuilder modelBuilder)  
  12.     {  
  13.         modelBuilder.Entity<EmployeeMaster>()  
  14.             .MapToStoredProcedures(s => s.Insert(u => u.HasName("InsertEmployee""dbo"))  
  15.                                             .Update(u => u.HasName("UpdateEmployee""dbo"))  
  16.                                             .Delete(u => u.HasName("DeleteEmployee""dbo"))  
  17.             );  
  18.     }  
  19. }  
Now I run the migration steps.
 
Step 1
 
Enable Migration
 
enable-migrations -ContextTypeName CodeFirstStoredProcedure.EntitiesContext -MigrationsDirectory:EntitiesMigrations
 
package source
 
Step 2
 
Add-Migration Configuration
 
Add-Migration -configuration CodeFirstStoredProcedure.EntitiesMigrations.Configuration InitialEntities
 
Package Manager Console
 
The add migration command generates a Dbmigration class. This DB Migration class has a definition for all the Stored Procedures.
  1. public partial class InitialEntities : DbMigration  
  2. {  
  3.     public override void Up()  
  4.     {  
  5.         CreateStoredProcedure(  
  6.             "dbo.InsertEmployee",  
  7.              p => new  
  8.             {  
  9.                 Code = p.String(),  
  10.                 Name = p.String(),  
  11.                 DepartmentId = p.Int(),  
  12.             },  
  13.             body:  
  14.                 @"INSERT [dbo].[EmployeeMasters]([Code], [Name], [DepartmentId])  
  15.             VALUES (@Code, @Name, @DepartmentId)  
  16.                         
  17.             DECLARE @EmployeeId int  
  18.             SELECT @EmployeeId = [EmployeeId]  
  19.             FROM [dbo].[EmployeeMasters]  
  20.             WHERE @@ROWCOUNT > 0 AND [EmployeeId] = scope_identity()  
  21.                         
  22.             SELECT t0.[EmployeeId]  
  23.             FROM [dbo].[EmployeeMasters] AS t0  
  24.             WHERE @@ROWCOUNT > 0 AND t0.[EmployeeId] = @EmployeeId"  
  25.         );  
  26.   
  27.         CreateStoredProcedure(  
  28.             "dbo.UpdateEmployee",  
  29.             p => new  
  30.             {  
  31.                 EmployeeId = p.Int(),  
  32.                 Code = p.String(),  
  33.                 Name = p.String(),  
  34.                 DepartmentId = p.Int(),  
  35.             },  
  36.             body:  
  37.                 @"UPDATE [dbo].[EmployeeMasters]  
  38.             SET [Code] = @Code, [Name] = @Name, [DepartmentId] = @DepartmentId  
  39.             WHERE ([EmployeeId] = @EmployeeId)"  
  40.         );  
  41.   
  42.         CreateStoredProcedure(  
  43.             "dbo.DeleteEmployee",  
  44.             p => new  
  45.             {  
  46.                 EmployeeId = p.Int(),  
  47.             },  
  48.             body:  
  49.                 @"DELETE [dbo].[EmployeeMasters]  
  50.             WHERE ([EmployeeId] = @EmployeeId)"  
  51.         );  
  52.   
  53.     }  
  54.   
  55.     public override void Down()  
  56.     {  
  57.         DropStoredProcedure("dbo.DeleteEmployee");  
  58.         DropStoredProcedure("dbo.UpdateEmployee");  
  59.         DropStoredProcedure("dbo.InsertEmployee");  
  60.     }  
  61. }  
Step 3
 
Update-Database
 
Update-Database -configuration:CodeFirstStoredProcedure.EntitiesMigrations.Configuration -Verbose
 
update database configuration
 
Update database command creates tables and Stored Procedure and definition of the Stored Procedure are as the following:
  1. CREATE PROCEDURE [dbo].[InsertEmployee]  
  2.     @Code [nvarchar](max),  
  3.     @Name [nvarchar](max),  
  4.     @DepartmentId [int]  
  5. AS  
  6. BEGIN  
  7.     INSERT [dbo].[EmployeeMasters]([Code], [Name], [DepartmentId])  
  8.     VALUES (@Code, @Name, @DepartmentId)  
  9.       
  10.     DECLARE @EmployeeId int  
  11.     SELECT @EmployeeId = [EmployeeId]  
  12.     FROM [dbo].[EmployeeMasters]  
  13.     WHERE @@ROWCOUNT > 0 AND [EmployeeId] = scope_identity()  
  14.       
  15.     SELECT t0.[EmployeeId]  
  16.     FROM [dbo].[EmployeeMasters] AS t0  
  17.     WHERE @@ROWCOUNT > 0 AND t0.[EmployeeId] = @EmployeeId  
  18. END  
  19.   
  20. GO  
  21.   
  22. CREATE PROCEDURE [dbo].[UpdateEmployee]  
  23.     @EmployeeId [int],  
  24.     @Code [nvarchar](max),  
  25.     @Name [nvarchar](max),  
  26.     @DepartmentId [int]  
  27. AS  
  28. BEGIN  
  29.     UPDATE [dbo].[EmployeeMasters]  
  30.     SET [Code] = @Code, [Name] = @Name, [DepartmentId] = @DepartmentId  
  31.     WHERE ([EmployeeId] = @EmployeeId)  
  32. END  
  33.   
  34. GO  
  35.   
  36. CREATE PROCEDURE [dbo].[DeleteEmployee]  
  37.     @EmployeeId [int]  
  38. AS  
  39. BEGIN  
  40.     DELETE [dbo].[EmployeeMasters]  
  41.     WHERE ([EmployeeId] = @EmployeeId)  
  42. END  
store procedure in database
 
Test Code
 
In the test code, I am inserting a record into the EmployeeMaster table:
  1. static void Main(string[] args)  
  2. {  
  3.     using (EntitiesContext  context = new EntitiesContext())  
  4.     {  
  5.         EmployeeMaster employee = new EmployeeMaster();  
  6.         employee.Code = "A0001";  
  7.         employee.Name = "Jignesh Trivedi";  
  8.         employee.DepartmentId = 1;  
  9.         context.Employees.Add(employee);  
  10.         context.SaveChanges();  
  11.         Console.ReadLine();  
  12.     }  
  13. }  
The Interception/SQL logging feature is introduced in Entity Framework 6. Entity Framework sends commands (or an equivalent SQL query) to the database to do a CRUD operation and this command can be intercepted by the application code of Entity Framework. This feature of the Entity Framework is to capture an equivalent SQL query generated by Entity Framework internally and provide it as output. The following code can be used to send output to the console.
  1. public EntitiesContext() : base("name=Entities")  
  2. {  
  3.     Database.Log = Console.WriteLine;  
  4. }  
The following is the SQL logging output of the code above:
 
SQL logging output
 
logging output
 

Summary

 
Using Entity Framework 6.0 and above, we can configure our code first model to use a Stored Procedure for a few or all entities of the model.


Recommended Free Ebook
Similar Articles