"
ASP.NET (snapshot 2017) Microsoft documentation and samples

Getting started with ASP.NET Core and Entity Framework 6

By Paweł Grudzień, Damien Pontifex, and Tom Dykstra

This article shows how to use Entity Framework 6 in an ASP.NET Core application.

Overview

To use Entity Framework 6, your project has to compile against .NET Framework, as Entity Framework 6 does not support .NET Core. If you need cross-platform features you will need to upgrade to Entity Framework Core.

The recommended way to use Entity Framework 6 in an ASP.NET Core application is to put the EF6 context and model classes in a class library project that targets the full framework. Add a reference to the class library from the ASP.NET Core project. See the sample Visual Studio solution with EF6 and ASP.NET Core projects.

You can’t put an EF6 context in an ASP.NET Core project because .NET Core projects don’t support all of the functionality that EF6 commands such as Enable-Migrations require.

Regardless of project type in which you locate your EF6 context, only EF6 command-line tools work with an EF6 context. For example, Scaffold-DbContext is only available in Entity Framework Core. If you need to do reverse engineering of a database into an EF6 model, see Code First to an Existing Database.

Reference full framework and EF6 in the ASP.NET Core project

Your ASP.NET Core project needs to reference .NET framework and EF6. For example, the .csproj file of your ASP.NET Core project will look similar to the following example (only relevant parts of the file are shown).

[!code-xmlMain]

   1:  <Project Sdk="Microsoft.NET.Sdk.Web">
   2:   
   3:    <PropertyGroup>
   4:      <TargetFramework>net452</TargetFramework>
   5:      <PreserveCompilationContext>true</PreserveCompilationContext>
   6:      <AssemblyName>MVCCore</AssemblyName>
   7:      <OutputType>Exe</OutputType>
   8:      <PackageId>MVCCore</PackageId>
   9:    </PropertyGroup>
  10:   
  11:    <ItemGroup>
  12:      <None Include="App.config" />
  13:      <Content Update="wwwroot\**\*;Views\**\*;Areas\**\Views;appsettings.json;web.config">
  14:        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
  15:      </Content>
  16:      <ProjectReference Include="..\EF6\EF6.csproj" />
  17:    </ItemGroup>
  18:   
  19:    <ItemGroup>
  20:      <PackageReference Include="EntityFramework" Version="6.1.3" />
  21:      <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.0.1" />
  22:      <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.0.2" />
  23:      <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.0.1" />
  24:      <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.0.2" />
  25:      <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.0.1" />
  26:      <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.0.1" />
  27:      <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.1" />
  28:      <PackageReference Include="Microsoft.Extensions.Logging" Version="1.0.1" />
  29:      <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.0.1" />
  30:      <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.0.1" />
  31:      <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.0.1" />
  32:      <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink.Loader" Version="14.0.1" />
  33:    </ItemGroup>
  34:   
  35:    <ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
  36:      <Reference Include="System" />
  37:      <Reference Include="Microsoft.CSharp" />
  38:    </ItemGroup>
  39:   
  40:    <Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
  41:      <Exec Command="bower install" />
  42:      <Exec Command="dotnet bundle" />
  43:    </Target>
  44:   
  45:    <ItemGroup>
  46:      <DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.2.301" />
  47:    </ItemGroup>
  48:   
  49:  </Project>

If you’re creating a new project, use the ASP.NET Core Web Application (.NET Framework) template.

Handle connection strings

The EF6 command-line tools that you’ll use in the EF6 class library project require a default constructor so they can instantiate the context. But you’ll probably want to specify the connection string to use in the ASP.NET Core project, in which case your context constructor must have a parameter that lets you pass in the connection string. Here’s an example.

[!code-csharpMain]

   1:  using System.Data.Entity;
   2:  using System.Data.Entity.ModelConfiguration.Conventions;
   3:  using EF6.Models;
   4:   
   5:  namespace EF6
   6:  {
   7:      #region snippet_Constructor
   8:      public class SchoolContext : DbContext
   9:      {
  10:          public SchoolContext(string connString) : base(connString)
  11:          {
  12:          }
  13:          #endregion
  14:   
  15:          public DbSet<Student> Students { get; set; }
  16:          public DbSet<Enrollment> Enrollments { get; set; }
  17:          public DbSet<Course> Courses { get; set; }
  18:   
  19:          protected override void OnModelCreating(DbModelBuilder modelBuilder)
  20:          {
  21:              modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
  22:          }
  23:      }
  24:  }

Since your EF6 context doesn’t have a parameterless constructor, your EF6 project has to provide an implementation of IDbContextFactory. The EF6 command-line tools will find and use that implementation so they can instantiate the context. Here’s an example.

[!code-csharpMain]

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Data.Entity.Infrastructure;
   4:  using System.Linq;
   5:  using System.Text;
   6:  using System.Threading.Tasks;
   7:   
   8:  namespace EF6
   9:  {
  10:      #region snippet_IDbContextFactory
  11:      public class SchoolContextFactory : IDbContextFactory<SchoolContext>
  12:      {
  13:          public SchoolContext Create()
  14:          {
  15:              return new EF6.SchoolContext("Server=(localdb)\\mssqllocaldb;Database=EF6MVCCore;Trusted_Connection=True;MultipleActiveResultSets=true");
  16:          }
  17:      }
  18:      #endregion
  19:  }

In this sample code, the IDbContextFactory implementation passes in a hard-coded connection string. This is the connection string that the command-line tools will use. You’ll want to implement a strategy to ensure that the class library uses the same connection string that the calling application uses. For example, you could get the value from an environment variable in both projects.

Set up dependency injection in the ASP.NET Core project

In the Core project’s Startup.cs file, set up the EF6 context for dependency injection (DI) in ConfigureServices. EF context objects should be scoped for a per-request lifetime.

[!code-csharpMain]

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Threading.Tasks;
   5:  using Microsoft.AspNetCore.Builder;
   6:  using Microsoft.AspNetCore.Hosting;
   7:  using Microsoft.Extensions.Configuration;
   8:  using Microsoft.Extensions.DependencyInjection;
   9:  using Microsoft.Extensions.Logging;
  10:  using EF6;
  11:  using EF6.Models;
  12:   
  13:  namespace MVCCore
  14:  {
  15:      public class Startup
  16:      {
  17:          public Startup(IHostingEnvironment env)
  18:          {
  19:              var builder = new ConfigurationBuilder()
  20:                  .SetBasePath(env.ContentRootPath)
  21:                  .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  22:                  .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
  23:                  .AddEnvironmentVariables();
  24:              Configuration = builder.Build();
  25:          }
  26:   
  27:          public IConfigurationRoot Configuration { get; }
  28:   
  29:          // This method gets called by the runtime. Use this method to add services to the container.
  30:          #region snippet_ConfigureServices
  31:          public void ConfigureServices(IServiceCollection services)
  32:          {
  33:              // Add framework services.
  34:              services.AddMvc();
  35:              services.AddScoped<SchoolContext>(_ => new SchoolContext(Configuration.GetConnectionString("DefaultConnection")));
  36:          }
  37:          #endregion  
  38:   
  39:          // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  40:          public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
  41:          {
  42:              loggerFactory.AddConsole(Configuration.GetSection("Logging"));
  43:              loggerFactory.AddDebug();
  44:   
  45:              if (env.IsDevelopment())
  46:              {
  47:                  app.UseDeveloperExceptionPage();
  48:                  app.UseBrowserLink();
  49:              }
  50:              else
  51:              {
  52:                  app.UseExceptionHandler("/Home/Error");
  53:              }
  54:   
  55:              app.UseStaticFiles();
  56:   
  57:              app.UseMvc(routes =>
  58:              {
  59:                  routes.MapRoute(
  60:                      name: "default",
  61:                      template: "{controller=Home}/{action=Index}/{id?}");
  62:              });
  63:          }
  64:      }
  65:  }

You can then get an instance of the context in your controllers by using DI. The code is similar to what you’d write for an EF Core context:

[!code-csharpMain]

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Data;
   4:  using System.Data.Entity;
   5:  using System.Linq;
   6:  using System.Threading.Tasks;
   7:  using Microsoft.AspNetCore.Mvc;
   8:  using Microsoft.AspNetCore.Mvc.Rendering;
   9:  using EF6;
  10:  using EF6.Models;
  11:   
  12:  namespace ContosoUniversity.Controllers
  13:  {
  14:      #region snippet_ContextInController
  15:      public class StudentsController : Controller
  16:      {
  17:          private readonly SchoolContext _context;
  18:   
  19:          public StudentsController(SchoolContext context)
  20:          {
  21:              _context = context;
  22:          }
  23:          #endregion
  24:          // GET: Students
  25:          public async Task<IActionResult> Index()
  26:          {
  27:              return View(await _context.Students.ToListAsync());
  28:          }
  29:   
  30:          // GET: Students/Details/5
  31:          public async Task<IActionResult> Details(int? id)
  32:          {
  33:              if (id == null)
  34:              {
  35:                  return NotFound();
  36:              }
  37:   
  38:              var student = await _context.Students.SingleOrDefaultAsync(m => m.ID == id);
  39:              if (student == null)
  40:              {
  41:                  return NotFound();
  42:              }
  43:   
  44:              return View(student);
  45:          }
  46:   
  47:          // GET: Students/Create
  48:          public IActionResult Create()
  49:          {
  50:              return View();
  51:          }
  52:   
  53:          // POST: Students/Create
  54:          // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
  55:          // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
  56:          [HttpPost]
  57:          [ValidateAntiForgeryToken]
  58:          public async Task<IActionResult> Create([Bind("EnrollmentDate,FirstMidName,LastName")] Student student)
  59:          {
  60:              if (ModelState.IsValid)
  61:              {
  62:                  _context.Students.Add(student);
  63:                  await _context.SaveChangesAsync();
  64:                  return RedirectToAction("Index");
  65:              }
  66:              return View(student);
  67:          }
  68:   
  69:          // GET: Students/Edit/5
  70:          public async Task<IActionResult> Edit(int? id)
  71:          {
  72:              if (id == null)
  73:              {
  74:                  return NotFound();
  75:              }
  76:   
  77:              var student = await _context.Students.SingleOrDefaultAsync(m => m.ID == id);
  78:              if (student == null)
  79:              {
  80:                  return NotFound();
  81:              }
  82:              return View(student);
  83:          }
  84:   
  85:          // POST: Students/Edit/5
  86:          // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
  87:          // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
  88:          [HttpPost]
  89:          [ValidateAntiForgeryToken]
  90:          public async Task<IActionResult> Edit(int id, [Bind("ID,EnrollmentDate,FirstMidName,LastName")] Student student)
  91:          {
  92:              if (id != student.ID)
  93:              {
  94:                  return NotFound();
  95:              }
  96:   
  97:              if (ModelState.IsValid)
  98:              {
  99:                  _context.Students.Attach(student);
 100:                  _context.Entry(student).State = EntityState.Modified;
 101:                  await _context.SaveChangesAsync();
 102:                  return RedirectToAction("Index");
 103:              }
 104:              return View(student);
 105:          }
 106:   
 107:          // GET: Students/Delete/5
 108:          public async Task<IActionResult> Delete(int? id)
 109:          {
 110:              if (id == null)
 111:              {
 112:                  return NotFound();
 113:              }
 114:   
 115:              var student = await _context.Students.SingleOrDefaultAsync(m => m.ID == id);
 116:              if (student == null)
 117:              {
 118:                  return NotFound();
 119:              }
 120:   
 121:              return View(student);
 122:          }
 123:   
 124:          // POST: Students/Delete/5
 125:          [HttpPost, ActionName("Delete")]
 126:          [ValidateAntiForgeryToken]
 127:          public async Task<IActionResult> DeleteConfirmed(int id)
 128:          {
 129:              var student = await _context.Students.SingleOrDefaultAsync(m => m.ID == id);
 130:              _context.Students.Remove(student);
 131:              await _context.SaveChangesAsync();
 132:              return RedirectToAction("Index");
 133:          }
 134:   
 135:      }
 136:  }

Sample application

For a working sample application, see the sample Visual Studio solution that accompanies this article.

This sample can be created from scratch by the following steps in Visual Studio:

Summary

This article has provided basic guidance for using Entity Framework 6 in an ASP.NET Core application.

Additional Resources



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnetcore/data/entity-framework-6.htm
< THANKS ME>