Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection

In this post, we will see how to connect MS SQL, MongoDB, and MySQL databases from the same MVC application. We will use dependency injection with Unity package to achieve this.

Introduction

In my previous article on C# Corner, we saw how to create a Web API and consume that API from an MVC application. In this article, we will see how to create a Web API using repository patterns and will consume this API from an MVC application. We will use a single interface for implementing three different services for MS SQL, MongoDB and MySQL databases. We will call these repository classes from a single Web API and consume this API from the MVC controller.

Hence, we can connect the same MVC application with different databases very easily. We just need to instantiate the appropriate service for the required database type. It is very simple. We can see all the implementation step by step.

We will create a simple Employee application to demonstrate these functionalities. We must create a database and a table in MS SQL server and MySQL server. Please note, in MongoDB database and the collection will be created automatically once the application starts.

Create an “Employees” table in MS SQL Server

 
We are using Entity Framework to connect MS SQL database. So, I am giving the table name in plural format.
  1. USE [SarathDB]    
  2. GO    
  3.     
  4. CREATE TABLE [dbo].[Employees](    
  5.     [Id] [nvarchar](50) NOT NULL,    
  6.     [Name] [nvarchar](50) NULL,    
  7.     [Gender] [nvarchar](10) NULL,    
  8.     [Company] [nvarchar](50) NULL,    
  9.     [Designation] [nvarchar](50) NULL,  
  10.     [DbType] [nvarchar](10) NULL,    
  11.  CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED     
  12.     (    
  13.         [Id] ASC    
  14.     )    
  15. )    
  16. GO    
Create “Employee” table in My SQL Server.
  1. CREATE DATABASE SarathMySQLDB;          
  2. USE SarathMySQLDB;  
  3.   
  4. CREATE TABLE Employee       
  5. (Id VARCHAR(50) PRIMARY KEY,        
  6.  Name VARCHAR(50),        
  7.  Gender VARCHAR(50),        
  8.  Company VARCHAR(50),        
  9.  Designation VARCHAR(50),        
  10.  DbType VARCHAR(50)  
  11. );  

Create a Visual Studio project with MVC and Web API templates

We can create a new project in VS 2015/2017. I am using a free 2017 community edition.

Please choose MVC template and choose the Web API option so, that we can get the bootstrapping for Web API in our project. No need to change any other default parameters.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

As I mentioned earlier, we will connect three different types of servers with the same MVC application. We are using entity framework for connecting the MS SQL server. We will use MongoDB.Driver package for connecting the MongoDB database. We will use MySql.Data package for connecting MySQL server. We will use the Unity container for dependency injection.

We can now install below NuGet packages to project one by one.

Install Unity package for dependency injection.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 
 
We can install the latest Unity package for our project.
 
Install the EntityFramework package for connecting the MS SQL database.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
Install MongoDB.Driver package to connect MongoDB database.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
You must be very careful about the version of this package. The latest MongoDB package versions are not supported in .NET framework 4.5 version or below versions. You must install the MongoDB driver version equal to or below 2.7.3.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
Install MySql.Data package to connect MySQL database.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
Like MongoDB package, the latest MySQL packages are also not supported by .NET framework 4.5 version or below versions. You must choose version 6.9.12 or below version to compatible with .NET 4.5 version.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 
 
We can create “UnityResolver” class inside the “Resolver” folder which will be derived from “IDependencyResolver” interface.
 
UnityResolver.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Web.Http.Dependencies;  
  4. using Unity;  
  5.   
  6. namespace MVCWithDifferentDatabases.Resolver  
  7. {  
  8.     public class UnityResolver : IDependencyResolver  
  9.     {  
  10.         protected IUnityContainer container;  
  11.   
  12.         public UnityResolver(IUnityContainer container)  
  13.         {  
  14.             if (container == null)  
  15.             {  
  16.                 throw new ArgumentNullException("container");  
  17.             }  
  18.             this.container = container;  
  19.         }  
  20.   
  21.         public object GetService(Type serviceType)  
  22.         {  
  23.             try  
  24.             {  
  25.                 return container.Resolve(serviceType);  
  26.             }  
  27.             catch (ResolutionFailedException)  
  28.             {  
  29.                 return null;  
  30.             }  
  31.         }  
  32.   
  33.         public IEnumerable<object> GetServices(Type serviceType)  
  34.         {  
  35.             try  
  36.             {  
  37.                 return container.ResolveAll(serviceType);  
  38.             }  
  39.             catch (ResolutionFailedException)  
  40.             {  
  41.                 return new List<object>();  
  42.             }  
  43.         }  
  44.   
  45.         public IDependencyScope BeginScope()  
  46.         {  
  47.             var child = container.CreateChildContainer();  
  48.             return new UnityResolver(child);  
  49.         }  
  50.   
  51.         public void Dispose()  
  52.         {  
  53.             container.Dispose();  
  54.         }  
  55.     }  
  56. }  

We will register our three services for different repository classes with this UnityResolver in the WebApiConfig class later.

We can create the common “Employee” class now.

We will use the same Employee class for all database types. In MS SQL and My SQL databases, we will provide a GUID while creating the new employee record. But MongoDB will automatically create object id for each record. Hence, we will add two attributes to the Id property in Employee class.

Employee.cs
  1. using MongoDB.Bson;  
  2. using MongoDB.Bson.Serialization.Attributes;  
  3.   
  4. namespace MVCWithDifferentDatabases.Models  
  5. {  
  6.     public class Employee  
  7.     {  
  8.         [BsonId]  
  9.         [BsonRepresentation(BsonType.ObjectId)]  
  10.         public string Id { getset; }  
  11.         public string Name { getset; }  
  12.         public string Gender { getset; }  
  13.         public string Company { getset; }  
  14.         public string Designation { getset; }  
  15.         public string DbType { getset; }  
  16.     }  
  17. }  

We can create “SqlDbContext” class and derives DbContext class insides this class.

SqlDbContext.cs

  1. using System.Data.Entity;  
  2.   
  3. namespace MVCWithDifferentDatabases.Models  
  4. {  
  5.     public class SqlDbContext : DbContext  
  6.     {  
  7.         public SqlDbContext() : base("name=SqlConnection")  
  8.         {  
  9.         }  
  10.         public DbSet<Employee> Employees { getset; }  
  11.     }  
  12. }  

We have used a connection “SqlConnection” in the above DbContext class. We must create the connection string in Web.Config file.

Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
  1. <connectionStrings>    
  2.     <add name="SqlConnection"     
  3.          connectionString="Data Source=MURUGAN\SQL2017ML; Initial Catalog=SarathDB; Integrated Security=True; MultipleActiveResultSets=True;"     
  4.          providerName="System.Data.SqlClient" />    
  5.   </connectionStrings>  

We must create two key-value pairs in Web.Config file under “appSettings” section for MongoDB and MySQL connections. We will use these connection strings later with corresponding repository classes.

Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

We can create a DbContext for MongoDB connection. Please note, we are not using Entity Framework for MongoDB data connectivity. Instead, you are using MongoDB driver package.

MongoDbContext.cs
  1. using MongoDB.Driver;  
  2.   
  3. namespace MVCWithDifferentDatabases.Models  
  4. {  
  5.     public class MongoDbContext  
  6.     {  
  7.         private readonly IMongoDatabase _mongoDb;  
  8.         public MongoDbContext()  
  9.         {  
  10.             var client = new MongoClient("mongodb://localhost:27017");  
  11.             _mongoDb = client.GetDatabase("SarathMongoDB");  
  12.         }  
  13.         public IMongoCollection<Employee> Employee  
  14.         {  
  15.             get  
  16.             {  
  17.                 return _mongoDb.GetCollection<Employee>("Employee");  
  18.             }  
  19.         }  
  20.     }  
  21. }  

We are following the repository pattern in this application. We can create a “IEmployeeRepository” interface and define all the methods here.

IEmployeeRepository.cs
  1. using System.Collections.Generic;  
  2. using System.Threading.Tasks;  
  3.   
  4. namespace MVCWithDifferentDatabases.Models  
  5. {  
  6.     public interface IEmployeeRepository  
  7.     {  
  8.         Task Add(Employee employee);  
  9.         Task Update(Employee employee);  
  10.         Task Delete(string id);  
  11.         Task<Employee> GetEmployee(string id);  
  12.         Task<IEnumerable<Employee>> GetEmployees();  
  13.     }  
  14. }  

We can implement separate repository service classes for MS SQL, MongoDB and MySQL and implement CRUD operations inside these classes.

We are going to implement the SQL repository now.

EmployeeSqlRepository.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Data.Entity;  
  4. using System.Linq;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace MVCWithDifferentDatabases.Models  
  8. {  
  9.     public class EmployeeSqlRepository : IEmployeeRepository, IDisposable  
  10.     {  
  11.         private readonly SqlDbContext db = new SqlDbContext();  
  12.         bool disposed = false;  
  13.         public async Task Add(Employee employee)  
  14.         {  
  15.             employee.Id = Guid.NewGuid().ToString();  
  16.             employee.DbType = "MS SQL";  
  17.   
  18.             db.Employees.Add(employee);  
  19.             try  
  20.             {  
  21.                 await db.SaveChangesAsync();  
  22.             }  
  23.             catch  
  24.             {  
  25.                 throw;  
  26.             }  
  27.         }  
  28.         public async Task<Employee> GetEmployee(string id)  
  29.         {  
  30.             try  
  31.             {  
  32.                 Employee employee = await db.Employees.FindAsync(id);  
  33.                 if (employee == null)  
  34.                 {  
  35.                     return null;  
  36.                 }  
  37.                 return employee;  
  38.             }  
  39.             catch  
  40.             {  
  41.                 throw;  
  42.             }  
  43.         }  
  44.         public async Task<IEnumerable<Employee>> GetEmployees()  
  45.         {  
  46.             try  
  47.             {  
  48.                 var employees = await db.Employees.ToListAsync();  
  49.                 return employees.AsQueryable();  
  50.             }  
  51.             catch  
  52.             {  
  53.                 throw;  
  54.             }  
  55.         }  
  56.         public async Task Update(Employee employee)  
  57.         {  
  58.             try  
  59.             {  
  60.                 db.Entry(employee).State = EntityState.Modified;  
  61.                 await db.SaveChangesAsync();  
  62.             }  
  63.             catch  
  64.             {  
  65.                 throw;  
  66.             }  
  67.         }  
  68.         public async Task Delete(string id)  
  69.         {  
  70.             try  
  71.             {  
  72.                 Employee employee = await db.Employees.FindAsync(id);  
  73.                 db.Employees.Remove(employee);  
  74.                 await db.SaveChangesAsync();  
  75.             }  
  76.             catch  
  77.             {  
  78.                 throw;  
  79.             }  
  80.         }  
  81.   
  82.         private bool EmployeeExists(string id)  
  83.         {  
  84.             return db.Employees.Count(e => e.Id == id) > 0;  
  85.         }  
  86.   
  87.         ~EmployeeSqlRepository()  
  88.         {  
  89.             if (!disposed)  
  90.             {  
  91.                 disposed = true;  
  92.                 Dispose(true);  
  93.             }  
  94.         }  
  95.   
  96.         protected virtual void Dispose(bool disposing)  
  97.         {  
  98.             if (disposing)  
  99.             {  
  100.                 db.Dispose();  
  101.             }  
  102.         }  
  103.   
  104.         public void Dispose()  
  105.         {  
  106.             if (!disposed)  
  107.             {  
  108.                 disposed = true;  
  109.                 Dispose(true);  
  110.                 GC.SuppressFinalize(this);  
  111.             }  
  112.         }  
  113.     }  
  114. }  

I have implemented all CRUD actions (total 5 methods) inside the above class. I have also implemented the “Dispose” method to destruct the db context instance.

We can implement the MongoDB repository now.
 
EmployeeMongoRepository.cs
  1. using MongoDB.Driver;  
  2. using System.Collections.Generic;  
  3. using System.Threading.Tasks;  
  4.   
  5. namespace MVCWithDifferentDatabases.Models  
  6. {  
  7.     public class EmployeeMongoRepository : IEmployeeRepository  
  8.     {  
  9.         MongoDbContext db = new MongoDbContext();  
  10.         public async Task Add(Employee employee)  
  11.         {  
  12.             try  
  13.             {  
  14.                 employee.DbType = "MongoDB";  
  15.                 await db.Employee.InsertOneAsync(employee);  
  16.             }  
  17.             catch  
  18.             {  
  19.                 throw;  
  20.             }  
  21.         }  
  22.         public async Task<Employee> GetEmployee(string id)  
  23.         {  
  24.             try  
  25.             {  
  26.                 FilterDefinition<Employee> filter = Builders<Employee>.Filter.Eq("Id", id);  
  27.                 return await db.Employee.Find(filter).FirstOrDefaultAsync();  
  28.             }  
  29.             catch  
  30.             {  
  31.                 throw;  
  32.             }  
  33.         }  
  34.         public async Task<IEnumerable<Employee>> GetEmployees()  
  35.         {  
  36.             try  
  37.             {  
  38.                 return await db.Employee.Find(_ => true).ToListAsync();  
  39.             }  
  40.             catch  
  41.             {  
  42.                 throw;  
  43.             }  
  44.         }  
  45.         public async Task Update(Employee employee)  
  46.         {  
  47.             try  
  48.             {  
  49.                 await db.Employee.ReplaceOneAsync(filter: g => g.Id == employee.Id, replacement: employee);  
  50.             }  
  51.             catch  
  52.             {  
  53.                 throw;  
  54.             }  
  55.         }  
  56.         public async Task Delete(string id)  
  57.         {  
  58.             try  
  59.             {  
  60.                 FilterDefinition<Employee> data = Builders<Employee>.Filter.Eq("Id", id);  
  61.                 await db.Employee.DeleteOneAsync(data);  
  62.             }  
  63.             catch  
  64.             {  
  65.                 throw;  
  66.             }  
  67.         }  
  68.     }  
  69. }  

We can implement the My SQL repository now.

EmployeeMySqlRepository.cs
  1. using MySql.Data.MySqlClient;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Configuration;  
  5. using System.Data;  
  6. using System.Threading.Tasks;  
  7.   
  8. namespace MVCWithDifferentDatabases.Models  
  9. {  
  10.     public class EmployeeMySqlRepository : IEmployeeRepository  
  11.     {  
  12.   
  13.         private MySqlConnection GetConnection()  
  14.         {  
  15.             return new MySqlConnection(ConfigurationManager.AppSettings["MySQLConnection"]);  
  16.         }  
  17.   
  18.         public async Task Add(Employee employee)  
  19.         {  
  20.             employee.Id = Guid.NewGuid().ToString();  
  21.             try  
  22.             {  
  23.                 using (MySqlConnection conn = GetConnection())  
  24.                 {  
  25.                     conn.Open();  
  26.                     var commandText = @"INSERT INTO Employee (Id,Name,Gender,Company,Designation,DbType) VALUES (@Id, @Name, @Gender, @Company, @Designation,'My SQL');";  
  27.   
  28.                     MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  29.   
  30.                     cmd.Parameters.Add(new MySqlParameter  
  31.                     {  
  32.                         ParameterName = "@Id",  
  33.                         DbType = DbType.String,  
  34.                         Value = employee.Id,  
  35.                     });  
  36.   
  37.                     cmd.Parameters.Add(new MySqlParameter  
  38.                     {  
  39.                         ParameterName = "@Name",  
  40.                         DbType = DbType.String,  
  41.                         Value = employee.Name,  
  42.                     });  
  43.   
  44.                     cmd.Parameters.Add(new MySqlParameter  
  45.                     {  
  46.                         ParameterName = "@Gender",  
  47.                         DbType = DbType.String,  
  48.                         Value = employee.Gender,  
  49.                     });  
  50.   
  51.                     cmd.Parameters.Add(new MySqlParameter  
  52.                     {  
  53.                         ParameterName = "@Company",  
  54.                         DbType = DbType.String,  
  55.                         Value = employee.Company,  
  56.                     });  
  57.   
  58.                     cmd.Parameters.Add(new MySqlParameter  
  59.                     {  
  60.                         ParameterName = "@Designation",  
  61.                         DbType = DbType.String,  
  62.                         Value = employee.Designation,  
  63.                     });  
  64.   
  65.                     await cmd.ExecuteNonQueryAsync();  
  66.   
  67.                 }  
  68.             }  
  69.             catch (Exception ex)  
  70.             {  
  71.                 throw;  
  72.             }  
  73.         }  
  74.         public async Task<Employee> GetEmployee(string id)  
  75.         {  
  76.             try  
  77.             {  
  78.                 using (MySqlConnection conn = GetConnection())  
  79.                 {  
  80.                     conn.Open();  
  81.                     var commandText = @"SELECT Name,Gender,Company,Designation FROM Employee Where Id=@Id;";  
  82.                     MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  83.                     cmd.Parameters.Add(new MySqlParameter  
  84.                     {  
  85.                         ParameterName = "@Id",  
  86.                         DbType = DbType.String,  
  87.                         Value = id,  
  88.                     });  
  89.   
  90.                     using (var reader = cmd.ExecuteReader())  
  91.                     {  
  92.                         if (await reader.ReadAsync())  
  93.                         {  
  94.                             return new Employee()  
  95.                             {  
  96.                                 Id = id,  
  97.                                 Name = await reader.GetFieldValueAsync<string>(0),  
  98.                                 Gender = await reader.GetFieldValueAsync<string>(1),  
  99.                                 Company = await reader.GetFieldValueAsync<string>(2),  
  100.                                 Designation = await reader.GetFieldValueAsync<string>(3)  
  101.                             };  
  102.                         }  
  103.                         else  
  104.                         {  
  105.                             return null;  
  106.                         }  
  107.   
  108.                     }  
  109.                 }  
  110.             }  
  111.             catch  
  112.             {  
  113.                 throw;  
  114.             }  
  115.         }  
  116.         public async Task<IEnumerable<Employee>> GetEmployees()  
  117.         {  
  118.             try  
  119.             {  
  120.                 List<Employee> list = new List<Employee>();  
  121.   
  122.                 using (MySqlConnection conn = GetConnection())  
  123.                 {  
  124.                     conn.Open();  
  125.                     var commandText = @"SELECT Id,Name,Gender,Company,Designation,DbType FROM Employee;";  
  126.                     MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  127.   
  128.                     using (var reader = cmd.ExecuteReader())  
  129.                     {  
  130.                         while (await reader.ReadAsync())  
  131.                         {  
  132.                             list.Add(new Employee()  
  133.                             {  
  134.                                 Id = await reader.GetFieldValueAsync<string>(0),  
  135.                                 Name = await reader.GetFieldValueAsync<string>(1),  
  136.                                 Gender = await reader.GetFieldValueAsync<string>(2),  
  137.                                 Company = await reader.GetFieldValueAsync<string>(3),  
  138.                                 Designation = await reader.GetFieldValueAsync<string>(4),  
  139.                                 DbType = await reader.GetFieldValueAsync<string>(5)  
  140.                             });  
  141.                         }  
  142.                     }  
  143.   
  144.                 }  
  145.                 return list;  
  146.             }  
  147.             catch  
  148.             {  
  149.                 throw;  
  150.             }  
  151.         }  
  152.         public async Task Update(Employee employee)  
  153.         {  
  154.             try  
  155.             {  
  156.                 using (MySqlConnection conn = GetConnection())  
  157.                 {  
  158.                     conn.Open();  
  159.                     var commandText = @"UPDATE Employee SET Name=@Name, Gender=@Gender, Company=@Company, Designation=@Designation  Where Id=@Id;";  
  160.   
  161.                     MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  162.   
  163.                     cmd.Parameters.Add(new MySqlParameter  
  164.                     {  
  165.                         ParameterName = "@Id",  
  166.                         DbType = DbType.String,  
  167.                         Value = employee.Id,  
  168.                     });  
  169.   
  170.                     cmd.Parameters.Add(new MySqlParameter  
  171.                     {  
  172.                         ParameterName = "@Name",  
  173.                         DbType = DbType.String,  
  174.                         Value = employee.Name,  
  175.                     });  
  176.   
  177.                     cmd.Parameters.Add(new MySqlParameter  
  178.                     {  
  179.                         ParameterName = "@Gender",  
  180.                         DbType = DbType.String,  
  181.                         Value = employee.Gender,  
  182.                     });  
  183.   
  184.                     cmd.Parameters.Add(new MySqlParameter  
  185.                     {  
  186.                         ParameterName = "@Company",  
  187.                         DbType = DbType.String,  
  188.                         Value = employee.Company,  
  189.                     });  
  190.   
  191.                     cmd.Parameters.Add(new MySqlParameter  
  192.                     {  
  193.                         ParameterName = "@Designation",  
  194.                         DbType = DbType.String,  
  195.                         Value = employee.Designation,  
  196.                     });  
  197.   
  198.                     await cmd.ExecuteNonQueryAsync();  
  199.                 }  
  200.             }  
  201.             catch  
  202.             {  
  203.                 throw;  
  204.             }  
  205.         }  
  206.         public async Task Delete(string id)  
  207.         {  
  208.             try  
  209.             {  
  210.                 using (MySqlConnection conn = GetConnection())  
  211.                 {  
  212.                     conn.Open();  
  213.                     var commandText = @"DELETE FROM Employee Where Id=@Id;";  
  214.   
  215.                     MySqlCommand cmd = new MySqlCommand(commandText, conn);  
  216.   
  217.                     cmd.Parameters.Add(new MySqlParameter  
  218.                     {  
  219.                         ParameterName = "@Id",  
  220.                         DbType = DbType.String,  
  221.                         Value = id,  
  222.                     });  
  223.   
  224.                     await cmd.ExecuteNonQueryAsync();  
  225.                 }  
  226.             }  
  227.             catch  
  228.             {  
  229.                 throw;  
  230.             }  
  231.         }  
  232.   
  233.     }  
  234. }  

Unlike SQL and MongoDB, here we have used traditional ADO.Net way to communicate with My SQL database. We have used MySql data library for that.

We can create our API controller inside the “Controllers” folder now. Please note, for all three types of databases, we will use a single API controller. We will inject the appropriate service through dependency injection.
 
EmployeesApiController.cs
  1. using MVCWithDifferentDatabases.Models;  
  2. using System.Collections.Generic;  
  3. using System.Threading.Tasks;  
  4. using System.Web.Http;  
  5.   
  6. namespace MVCWithDifferentDatabases.Controllers  
  7. {  
  8.     public class EmployeesApiController : ApiController  
  9.     {  
  10.         private IEmployeeRepository _iEmployeeRepository;  
  11.   
  12.         public EmployeesApiController(IEmployeeRepository iEmployeeRepository)  
  13.         {  
  14.             _iEmployeeRepository = iEmployeeRepository;  
  15.         }  
  16.         [HttpGet]  
  17.         [Route("api/Employees/Get")]  
  18.         public async Task<IEnumerable<Employee>> Get()  
  19.         {  
  20.             return await _iEmployeeRepository.GetEmployees();  
  21.         }  
  22.   
  23.         [HttpPost]  
  24.         [Route("api/Employees/Create")]  
  25.         public async Task CreateAsync([FromBody]Employee employee)  
  26.         {  
  27.             if (ModelState.IsValid)  
  28.             {  
  29.                 await _iEmployeeRepository.Add(employee);  
  30.             }  
  31.         }  
  32.   
  33.         [HttpGet]  
  34.         [Route("api/Employees/Details/{id}")]  
  35.         public async Task<Employee> Details(string id)  
  36.         {  
  37.             var result = await _iEmployeeRepository.GetEmployee(id);  
  38.             return result;  
  39.         }  
  40.   
  41.         [HttpPut]  
  42.         [Route("api/Employees/Edit")]  
  43.         public async Task EditAsync([FromBody]Employee employee)  
  44.         {  
  45.             if (ModelState.IsValid)  
  46.             {  
  47.                 await _iEmployeeRepository.Update(employee);  
  48.             }  
  49.         }  
  50.   
  51.         [HttpDelete]  
  52.         [Route("api/Employees/Delete/{id}")]  
  53.         public async Task DeleteConfirmedAsync(string id)  
  54.         {  
  55.             await _iEmployeeRepository.Delete(id);  
  56.         }  
  57.   
  58.         protected override void Dispose(bool disposing)  
  59.         {  
  60.             if (disposing)  
  61.             {  
  62.                 _iEmployeeRepository = null;  
  63.             }  
  64.             base.Dispose(disposing);  
  65.         }  
  66.     }  
  67. }  

We have created a service instance with IEmployeeRepository interface in above API class. All the CRUD actions are also implemented in this Web API class.

We can register the services in WebApiConfig.cs file. We have instantiated a Unity container and registered the appropriate service. You can change the service as per your need. Now we have registered the SQL service so that our Web API will communicate with SQL repository class. Later, we will change the service type and connect with other database types as well.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
WebApiConfig.cs
  1. using MVCWithDifferentDatabases.Models;  
  2. using MVCWithDifferentDatabases.Resolver;  
  3. using System.Web.Http;  
  4. using Unity;  
  5.   
  6. namespace MVCWithDifferentDatabases  
  7. {  
  8.     public static class WebApiConfig  
  9.     {  
  10.         public static void Register(HttpConfiguration config)  
  11.         {  
  12.             // Web API configuration and services  
  13.             var container = new UnityContainer();  
  14.             //container.RegisterType<IEmployeeRepository, EmployeeSqlRepository>();  
  15.             //container.RegisterType<IEmployeeRepository, EmployeeMongoRepository>();  
  16.             container.RegisterType<IEmployeeRepository, EmployeeMySqlRepository>();  
  17.             config.DependencyResolver = new UnityResolver(container);  
  18.   
  19.             // Web API routes  
  20.             config.MapHttpAttributeRoutes();  
  21.   
  22.             config.Routes.MapHttpRoute(  
  23.                 name: "DefaultApi",  
  24.                 routeTemplate: "api/{controller}/{id}",  
  25.                 defaults: new { id = RouteParameter.Optional }  
  26.             );  
  27.         }  
  28.     }  
  29. }  

We have completed our Web API design. If needed, you can check the Web API using Postman or any other tool. Please note down the URL of the application. We need to add this base URL in our Web.Config file because we will use this base URL in MVC controller.

We can create a new key-value pair in Web.Config file under “appSettings” section for base URL.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection

We have named the key as “apiBaseAddress” and gave the project URL as value. Please note our project will be running in localhost with port number 2000.

Create the MVC Controller using Scaffolding

 
We can create the MVC Controller using scaffolding template so that we will get all the views for CRUD actions easily. We will modify these views later.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

We can right-click the “Controller” folder and click “Add” and choose “New Scaffolded Item” to create a new MVC controller.

You can choose, “MVC 5 Controller with views, using Entity Framework” option. This will create all views for CRUD operations.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
We can choose the model class, data context class and give controller name as well. Please note, the system will automatically give a name for a controller. If needed, you can change it.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
You can click the “Add” button to proceed further. After a few moments, our Employees controller is created with all views.
 
You can see the views under “Views” -> “Employees” folder.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
We will modify some of the view files later. Let us modify the “EmployeesController” class now. Please note, by default MVC controller did not create actions as async. We must convert all these actions asynchronously. You can copy the below code and paste it inside the controller class.
 
EmployeesController.cs
  1. using MVCWithDifferentDatabases.Models;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Configuration;  
  5. using System.Linq;  
  6. using System.Net;  
  7. using System.Net.Http;  
  8. using System.Threading.Tasks;  
  9. using System.Web.Mvc;  
  10.   
  11. namespace MVCWithDifferentDatabases.Controllers  
  12. {  
  13.     public class EmployeesController : Controller  
  14.     {  
  15.         readonly string apiBaseAddress = ConfigurationManager.AppSettings["apiBaseAddress"];  
  16.         public async Task<ActionResult> Index()  
  17.         {  
  18.             IEnumerable<Employee> employees = null;  
  19.   
  20.             using (var client = new HttpClient())  
  21.             {  
  22.                 client.BaseAddress = new Uri(apiBaseAddress);  
  23.   
  24.                 var result = await client.GetAsync("employees/get");  
  25.   
  26.                 if (result.IsSuccessStatusCode)  
  27.                 {  
  28.                     employees = await result.Content.ReadAsAsync<IList<Employee>>();  
  29.                 }  
  30.                 else  
  31.                 {  
  32.                     employees = Enumerable.Empty<Employee>();  
  33.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  34.                 }  
  35.             }  
  36.             return View(employees);  
  37.         }  
  38.   
  39.         public async Task<ActionResult> Details(string id)  
  40.         {  
  41.             if (id == null)  
  42.             {  
  43.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  44.             }  
  45.   
  46.             Employee employee = null;  
  47.             using (var client = new HttpClient())  
  48.             {  
  49.                 client.BaseAddress = new Uri(apiBaseAddress);  
  50.   
  51.                 var result = await client.GetAsync($"employees/details/{id}");  
  52.   
  53.                 if (result.IsSuccessStatusCode)  
  54.                 {  
  55.                     employee = await result.Content.ReadAsAsync<Employee>();  
  56.                 }  
  57.                 else  
  58.                 {  
  59.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  60.                 }  
  61.             }  
  62.   
  63.             if (employee == null)  
  64.             {  
  65.                 return HttpNotFound();  
  66.             }  
  67.             return View(employee);  
  68.         }  
  69.   
  70.         public ActionResult Create()  
  71.         {  
  72.             return View();  
  73.         }  
  74.   
  75.         [HttpPost]  
  76.         [ValidateAntiForgeryToken]  
  77.         public async Task<ActionResult> Create([Bind(Include = "Name,Gender,Company,Designation")] Employee employee)  
  78.         {  
  79.             if (ModelState.IsValid)  
  80.             {  
  81.                 using (var client = new HttpClient())  
  82.                 {  
  83.                     client.BaseAddress = new Uri(apiBaseAddress);  
  84.   
  85.                     var response = await client.PostAsJsonAsync("employees/Create", employee);  
  86.                     if (response.IsSuccessStatusCode)  
  87.                     {  
  88.                         return RedirectToAction("Index");  
  89.                     }  
  90.                     else  
  91.                     {  
  92.                         ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  93.                     }  
  94.                 }  
  95.             }  
  96.             return View(employee);  
  97.         }  
  98.   
  99.         public async Task<ActionResult> Edit(string id)  
  100.         {  
  101.             if (id == null)  
  102.             {  
  103.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  104.             }  
  105.             Employee employee = null;  
  106.             using (var client = new HttpClient())  
  107.             {  
  108.                 client.BaseAddress = new Uri(apiBaseAddress);  
  109.   
  110.                 var result = await client.GetAsync($"employees/details/{id}");  
  111.   
  112.                 if (result.IsSuccessStatusCode)  
  113.                 {  
  114.                     employee = await result.Content.ReadAsAsync<Employee>();  
  115.                 }  
  116.                 else  
  117.                 {  
  118.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  119.                 }  
  120.             }  
  121.             if (employee == null)  
  122.             {  
  123.                 return HttpNotFound();  
  124.             }  
  125.             return View(employee);  
  126.         }  
  127.   
  128.         [HttpPost]  
  129.         [ValidateAntiForgeryToken]  
  130.         public async Task<ActionResult> Edit([Bind(Include = "Id,Name,Gender,Company,Designation")] Employee employee)  
  131.         {  
  132.             if (ModelState.IsValid)  
  133.             {  
  134.                 using (var client = new HttpClient())  
  135.                 {  
  136.                     client.BaseAddress = new Uri(apiBaseAddress);  
  137.                     var response = await client.PutAsJsonAsync("employees/edit", employee);  
  138.                     if (response.IsSuccessStatusCode)  
  139.                     {  
  140.                         return RedirectToAction("Index");  
  141.                     }  
  142.                     else  
  143.                     {  
  144.                         ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  145.                     }  
  146.                 }  
  147.                 return RedirectToAction("Index");  
  148.             }  
  149.             return View(employee);  
  150.         }  
  151.   
  152.         public async Task<ActionResult> Delete(string id)  
  153.         {  
  154.             if (id == null)  
  155.             {  
  156.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  157.             }  
  158.             Employee employee = null;  
  159.             using (var client = new HttpClient())  
  160.             {  
  161.                 client.BaseAddress = new Uri(apiBaseAddress);  
  162.   
  163.                 var result = await client.GetAsync($"employees/details/{id}");  
  164.   
  165.                 if (result.IsSuccessStatusCode)  
  166.                 {  
  167.                     employee = await result.Content.ReadAsAsync<Employee>();  
  168.                 }  
  169.                 else  
  170.                 {  
  171.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  172.                 }  
  173.             }  
  174.   
  175.             if (employee == null)  
  176.             {  
  177.                 return HttpNotFound();  
  178.             }  
  179.             return View(employee);  
  180.         }  
  181.   
  182.         [HttpPost, ActionName("Delete")]  
  183.         [ValidateAntiForgeryToken]  
  184.         public async Task<ActionResult> DeleteConfirmed(string id)  
  185.         {  
  186.             using (var client = new HttpClient())  
  187.             {  
  188.                 client.BaseAddress = new Uri(apiBaseAddress);  
  189.   
  190.                 var response = await client.DeleteAsync($"employees/delete/{id}");  
  191.                 if (response.IsSuccessStatusCode)  
  192.                 {  
  193.                     return RedirectToAction("Index");  
  194.                 }  
  195.                 else  
  196.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  197.             }  
  198.             return View();  
  199.         }  
  200.   
  201.     }  
  202. }  

You can see, we have defined an “apiBaseAddress” variable globally and got the value for apiBaseAddress from Web.Config file. We will use this value in all our controller actions.

Index Action
  1. public async Task<ActionResult> Index()  
  2.         {  
  3.             IEnumerable<Employee> employees = null;  
  4.   
  5.             using (var client = new HttpClient())  
  6.             {  
  7.                 client.BaseAddress = new Uri(apiBaseAddress);  
  8.   
  9.                 var result = await client.GetAsync("employees/get");  
  10.   
  11.                 if (result.IsSuccessStatusCode)  
  12.                 {  
  13.                     employees = await result.Content.ReadAsAsync<IList<Employee>>();  
  14.                 }  
  15.                 else  
  16.                 {  
  17.                     employees = Enumerable.Empty<Employee>();  
  18.                     ModelState.AddModelError(string.Empty, "Server error try after some time.");  
  19.                 }  
  20.             }  
  21.             return View(employees);  
  22.         }  

If you look at the index action, you can see, we have declared a “HttpClient” variable and using client.GetAsync method, we have got the employee data result from Web API and store in a “result” variable. We have again read the employee data from this result variable using “ReadAsync” method.

We have used the same approach in other action methods also. All the methods are self-explanatory. If you have any queries, please feel free to contact me.
 
We can now modify the Index view. Please copy the below and paste to Index view file.
 
Index.cshtml
  1. @model IEnumerable<MVCWithDifferentDatabases.Models.Employee>  
  2.   
  3. @{  
  4.     ViewBag.Title = "Employee List";  
  5. }  
  6.   
  7. <h3>Employee List</h3>  
  8.   
  9. <p>  
  10.     @Html.ActionLink("New Employee""Create")  
  11. </p>  
  12. <table class="table">  
  13.     <tr>  
  14.         <th>  
  15.             @Html.DisplayNameFor(model => model.Name)  
  16.         </th>  
  17.         <th>  
  18.             @Html.DisplayNameFor(model => model.Gender)  
  19.         </th>  
  20.         <th>  
  21.             @Html.DisplayNameFor(model => model.Company)  
  22.         </th>  
  23.         <th>  
  24.             @Html.DisplayNameFor(model => model.Designation)  
  25.         </th>  
  26.         <th>  
  27.             @Html.DisplayNameFor(model => model.DbType)  
  28.         </th>  
  29.         <th></th>  
  30.     </tr>  
  31.   
  32.     @foreach (var item in Model)  
  33.     {  
  34.         <tr>  
  35.             <td>  
  36.                 @Html.ActionLink(item.Name, "Details"new { id = item.Id })  
  37.             </td>  
  38.             <td>  
  39.                 @Html.DisplayFor(modelItem => item.Gender)  
  40.             </td>  
  41.             <td>  
  42.                 @Html.DisplayFor(modelItem => item.Company)  
  43.             </td>  
  44.             <td>  
  45.                 @Html.DisplayFor(modelItem => item.Designation)  
  46.             </td>  
  47.             <td>  
  48.                 @Html.DisplayFor(modelItem => item.DbType)  
  49.             </td>  
  50.             <td>  
  51.                 @Html.ActionLink("Edit""Edit"new { id = item.Id }) |  
  52.                 @Html.ActionLink("Delete""Delete"new { id = item.Id })  
  53.             </td>  
  54.         </tr>  
  55.     }  
  56.   
  57. </table>  

We have modified the existing “Index” view. We have removed the “Details” link from this view and instead, we have given a hyperlink in the employee name itself for details.

We can modify the “Create” view by removing the Id field. Because for us, employee Id will be created automatically while inserting new data. We have used system GUID for this.

Create.cshtml
  1. @model MVCWithDifferentDatabases.Models.Employee  
  2.   
  3. @{  
  4.     ViewBag.Title = "Create Employee";  
  5. }  
  6.   
  7. <h3>Create Employee</h3>  
  8.   
  9.   
  10. @using (Html.BeginForm())  
  11. {  
  12.     @Html.AntiForgeryToken()  
  13.   
  14.     <div class="form-horizontal">  
  15.         <hr />  
  16.         @Html.ValidationSummary(true""new { @class = "text-danger" })  
  17.   
  18.         <div class="form-group">  
  19.             @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })  
  20.             <div class="col-md-10">  
  21.                 @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })  
  22.                 @Html.ValidationMessageFor(model => model.Name, ""new { @class = "text-danger" })  
  23.             </div>  
  24.         </div>  
  25.   
  26.         <div class="form-group">  
  27.             @Html.LabelFor(model => model.Gender, htmlAttributes: new { @class = "control-label col-md-2" })  
  28.             <div class="col-md-10">  
  29.                 @Html.EditorFor(model => model.Gender, new { htmlAttributes = new { @class = "form-control" } })  
  30.                 @Html.ValidationMessageFor(model => model.Gender, ""new { @class = "text-danger" })  
  31.             </div>  
  32.         </div>  
  33.   
  34.         <div class="form-group">  
  35.             @Html.LabelFor(model => model.Company, htmlAttributes: new { @class = "control-label col-md-2" })  
  36.             <div class="col-md-10">  
  37.                 @Html.EditorFor(model => model.Company, new { htmlAttributes = new { @class = "form-control" } })  
  38.                 @Html.ValidationMessageFor(model => model.Company, ""new { @class = "text-danger" })  
  39.             </div>  
  40.         </div>  
  41.   
  42.         <div class="form-group">  
  43.             @Html.LabelFor(model => model.Designation, htmlAttributes: new { @class = "control-label col-md-2" })  
  44.             <div class="col-md-10">  
  45.                 @Html.EditorFor(model => model.Designation, new { htmlAttributes = new { @class = "form-control" } })  
  46.                 @Html.ValidationMessageFor(model => model.Designation, ""new { @class = "text-danger" })  
  47.             </div>  
  48.         </div>  
  49.   
  50.         <div class="form-group">  
  51.             <div class="col-md-offset-2 col-md-10">  
  52.                 <input type="submit" value="Create" class="btn btn-default" />  
  53.             </div>  
  54.         </div>  
  55.     </div>  
  56. }  
  57.   
  58. <div>  
  59.     @Html.ActionLink("Back to List""Index")  
  60. </div>  
  61.   
  62. @section Scripts {  
  63.     @Scripts.Render("~/bundles/jqueryval")  
  64. }  

We can run the application now. The home page will look like the below screenshot.

Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

We can click the “Employees” link and create a new employee record.

Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection
 
We can get the employee details in the grid after saving the information.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

Please note the above Db Type is “MS SQL”. We have automatically saved that field to the table while inserting the data.

We can change the service to MongoDB repository by injecting the service in WebApiConfig file. We will comment the SQL service from and uncomment the MongoDB service as given below.

Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

We need no more changes to connect the application with MongoDB. We can simply run the application again. The application will automatically connect with the MongoDB database.

We can create a new employee record. You will get the data as given below. Please look at the DbType field, it shows as “MongoDB”.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 
 
You can change the service to MySql repository by changing the dependency injection in WebApiConfig file.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

You can run the application again. Now the application will be connected to MySql server.

We can create a new employee record and get the details in the grid.
 
Connect MS SQL, MongoDB And MySQL Databases From Same MVC App Using Dependency Injection 

Please note the Db Type shown as “My SQL” for the above employee record.

We have created a single employee record in each MS SQL, MongoDB, and My SQL servers. You can also check the remaining CRUD actions with the application.
 

Conclusion

 
In this article, we have created each repository classes for MS SQL, MongoDB and My SQL servers with the same interface. We have created a Web API class using these repository services and consumed the API in an MVC application.
 
We have used Unity container to inject these services and run the application with MS SQL, MongoDB, and My SQL servers. I hope you understand the practical usage of dependency injection and Unity container from this application. Please feel free to give your valuable comments as feedback on this article and I will be happy to answer all your queries so that I can also be aware of anything I have missed in this article.