This post will demonstrate how to integrate Entity Framework for database operations, including migration setup, and use Autofac to create Dependency Injection (DI) in an ASP.NET MVC application. Code modularity, testability, and maintainability are all enhanced by this method.
Configuring Dependency Injection with Autofac
1. Install the Autofac packages first.
To install Autofac and its integration package for MVC, launch the Package Manager Console and execute the subsequent commands.
Install-Package Autofac
Install-Package Autofac.Mvc5
Step 2. Configure Autofac
Open Global.asax.cs and configure Autofac in the Application_Start method.
using Autofac;
using Autofac.Integration.Mvc;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using WebApplication2.Data;
using WebApplication2.IRepository;
using WebApplication2.Service;
namespace WebApplication2
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var builder = new ContainerBuilder();
// Register MVC controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
// Register DbContext for DI
builder.RegisterType<MyDbContext>().AsSelf().InstancePerRequest();
// Register your services here
builder.RegisterType<ProductService>().As<IProductService>();
// Build the Autofac container
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Regular MVC application start
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
Implementing Entity Framework and Migrations
Step 1. Install Entity Framework
Run the following command in the Package Manager Console to install Entity Framework:
Install-Package EntityFramework
Step 2. Create MyDbContext
In the WebApplication2.Data namespace, create a class named MyDbContext to represent your database context:
Create Model Class for Product.
using System.ComponentModel.DataAnnotations;
namespace WebApplication2.Models
{
public class Product
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}
Step 2. Create MyDbContext
In the WebApplication2.Data namespace, create a class named MyDbContext to represent your database context:
using System.Data.Entity;
using WebApplication2.Models;
namespace WebApplication2.Data
{
public class MyDbContext : DbContext
{
public MyDbContext() : base("SqlServerConnection")
{
}
// Define your entities here
public DbSet<Product> Products { get; set; }
}
}
Step 3. Enable Migrations
In the Package Manager Console, run the following command to enable migrations.
Enable-Migrations
Step 4. Create Initial Migration
Create an initial migration based on your current model.
Add-Migration InitialCreate
Step 5. Update Database
Apply the migration to the database:
Update-Database
Step 6. Add Connection String
Add a connection string for MyDbContext in the Web.config file.
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
https://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="SqlServerConnection" connectionString="Server=MUD\SQLEXPRESS2022;Database=DIAndMigInNetFrameWord;User Id=sa;Password=123456;" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.8" />
<httpRuntime targetFramework="4.8" />
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" />
<bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Web.Infrastructure" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.1.1.0" newVersion="8.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE="Web" /optionInfer+" />
</compilers>
</system.codedom>
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<!-- Removed SQLite and Npgsql providers -->
</providers>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<remove invariant="System.Data.SQLite" />
<remove invariant="Npgsql" />
<add name="SQL Server" invariant="System.Data.SqlClient" description=".NET Framework Data Provider for SQL Server" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</DbProviderFactories>
</system.data>
</configuration>
Creating the Service and Repository Layers
Step 1. Create IProductService Interface
In the WebApplication2.IRepository namespace defines an interface for the product service.
using System.Collections.Generic;
using WebApplication2.Models;
namespace WebApplication2.IRepository
{
public interface IProductService
{
IEnumerable<Product> GetAllProducts();
void AddProduct(Product product);
}
}
Step 2. Implement ProductService
In the WebApplication2.Service namespace, implement the ProductService class.
using System.Collections.Generic;
using System.Linq;
using WebApplication2.Data;
using WebApplication2.IRepository;
using WebApplication2.Models;
namespace WebApplication2.Service
{
public class ProductService : IProductService
{
private readonly MyDbContext _context;
public ProductService(MyDbContext context)
{
_context = context;
}
public IEnumerable<Product> GetAllProducts()
{
return _context.Products.ToList();
}
public void AddProduct(Product product)
{
_context.Products.Add(product);
_context.SaveChanges();
}
}
}
Step 3. Create the Product Model
In the WebApplication2.Data namespace, create a Product model class.
using System.ComponentModel.DataAnnotations;
namespace WebApplication2.Models
{
public class Product
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
}
Creating the MVC Controller
Create a controller to handle requests related to products.
Step 1. Create ProductController
In the Controllers folder, create a ProductController
using System.Web.Mvc;
using WebApplication2.IRepository;
using WebApplication2.Models;
namespace WebApplication2.Controllers
{
public class ProductController : Controller
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
public ActionResult Index()
{
var products = _productService.GetAllProducts();
return View(products);
}
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Product product)
{
if (ModelState.IsValid)
{
_productService.AddProduct(product);
return RedirectToAction("Index");
}
return View(product);
}
}
}
Step 2. Create the View
In the Views/Product folder, create a view named Index. cshtml.
@model IEnumerable<WebApplication2.Models.Product>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
@Html.ActionLink("Details", "Details", new { id=item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
Step 3. Create the View
In the Views/Product folder, create a view named Create. cshtml.
@model WebApplication2.Models.Product
@{
ViewBag.Title = "View";
}
<h2>View</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Step 3. Create the View
Add the controller and Actions link in Layout Files.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark">
<div class="container">
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" title="Toggle navigation" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
<li>@Html.ActionLink("About", "About", "Home", new { area = "" }, new { @class = "nav-link" })</li>
<li>@Html.ActionLink("Contact", "Contact", "Home", new { area = "" }, new { @class = "nav-link" })</li>
<li>@Html.ActionLink("Product", "Index", "Product", new { area = "" }, new { @class = "nav-link" })</li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
Database Creation
After doing all of this, just run the migration.
Create Initial Migration
After enabling migrations, generate the initial migration based on your current model:
Add-Migration InitialCreate
This command creates a migration class in the Migrations folder that defines the initial schema for your database based on the Product model and the MyDbContext.
Update Database
Now, apply the migration to the database with the following command.
Update-Database
This command will create the database and tables defined in your MyDbContext. If your connection string is set up correctly, the database will be created in your SQL Server instance.
Running the Application
- Run the application in Visual Studio.
- Navigate to http://localhost:8081/Product/Index
- You should see the products displayed in a table.
Output
Conclusion
In this article, we successfully implemented Dependency Injection using Autofac and integrated Entity Framework for data access in an ASP.NET MVC application. This setup allows for better separation of concerns, making the application easier to maintain and test. By following these steps, you can extend this architecture to accommodate more complex business logic, additional services, and different data operations as needed. Happy coding!