24 KiB
title | author | description | keywords | ms.author | manager | ms.date | ms.topic | ms.assetid | ms.technology | ms.prod | uid |
---|---|---|---|---|---|---|---|---|---|---|---|
Getting started with ASP.NET Core MVC and Entity Framework Core using Visual Studio | Microsoft Docs | tdykstra | ASP.NET Core, | tdykstra | wpickett | 10/14/2016 | article | b67c3d4a-f2bf-4132-a48b-4b0d599d7981 | aspnet | aspnet-core | data/ef-mvc/intro |
Getting started with ASP.NET Core MVC and Entity Framework Core using Visual Studio
The Contoso University sample web application demonstrates how to create ASP.NET Core 1.0 MVC web applications using Entity Framework Core 1.0 and Visual Studio 2015.
The sample application is a web site for a fictional Contoso University. It includes functionality such as student admission, course creation, and instructor assignments. This tutorial series explains how to build the Contoso University sample application from scratch. You can download the completed application.
EF Core 1.0 is the latest version of EF but does not yet have all the features of EF 6.x. For information about how to choose between EF 6.x and EF Core 1.0, see EF Core vs. EF6.x. If you choose EF 6.x, see the previous version of this tutorial series.
Prerequisites
-
Visual Studio 2015 with Update 3 or later.
Troubleshooting
If you run into a problem you can't resolve, you can generally find the solution by comparing your code to the completed project that you can download. For some common errors and how to solve them, see the Troubleshooting section of the last tutorial in the series. If you don't find what you need there, you can post questions to the ASP.NET Entity Framework forum, the Entity Framework forum, or StackOverflow.com for ASP.NET Core or EF Core.
The Contoso University Web Application
The application you'll be building in these tutorials is a simple university web site.
Users can view and update student, course, and instructor information. Here are a few of the screens you'll create.
The UI style of this site has been kept close to what's generated by the built-in templates, so that the tutorial can focus mainly on how to use the Entity Framework.
Create an ASP.NET Core MVC web application
Open Visual Studio 2015 and create a new ASP.NET Core C# web project named "ContosoUniversity".
-
From the File menu, select New > Project.
-
From the left pane, select Templates > Visual C# > Web.
-
Select the ASP.NET Core Web Application (.NET Core) project template.
-
Enter ContosoUniversity as the name and click OK.
-
Wait for the New ASP.NET Core Web Application (.NET Core) dialog to appear
-
Select the Web Application template and ensure that Authentication is set to Individual User Accounts.
-
Clear the Host in the cloud check box.
-
Click OK
[!NOTE] Don't miss setting authentication to Individual User Accounts. You won't be using authentication in this tutorial, but you need to enable it because of a limitation of .NET Core Preview 2 Visual Studio tooling. Scaffolding for MVC controllers and views only works when Individual User Accounts authentication is enabled.
Set up the site style
A few simple changes will set up the site menu, layout, and home page.
Open Views/Shared/_Layout.cshtml and make the following changes:
-
Change each occurrence of "ContosoUniversity" to "Contoso University". There are three occurrences.
-
Add menu entries for Students, Courses, Instructors, and Departments, and delete the Contact menu entry.
The changes are highlighted.
In Views/Home/Index.cshtml, replace the contents of the file with the following code to replace the text about ASP.NET and MVC with text about this application:
Press CTRL+F5 to run the project or choose Debug > Start Without Debugging from the menu. You see the home page with tabs for the pages you'll create in these tutorials.
Entity Framework Core NuGet packages
Because you used the Individual User Accounts option when you created the project, support for EF Core has already been installed.
If you want to add EF Core support to a new project that you create without the Individual User Accounts option, install the following NuGet packages:
-
The package for the database provider you want to target. To use SQL Server, the package is Microsoft.EntityFrameworkCore.SqlServer. For a list of available providers see Database Providers.
-
The package for the EF command-line tools: Microsoft.EntityFrameworkCore.Tools. This package is a preview release, so to install it you have to enable preview release installation. After installing the package, you also have to add a reference to it in the
tools
collection in the project.json file.
If you open the project.json file, you'll see that these packages are already installed.
Create the data model
Next you'll create entity classes for the Contoso University application. You'll start with the following three entities.
There's a one-to-many relationship between Student
and Enrollment
entities, and there's a one-to-many relationship between Course
and Enrollment
entities. In other words, a student can be enrolled in any number of courses, and a course can have any number of students enrolled in it.
In the following sections you'll create a class for each one of these entities.
The Student entity
In the Models folder, create a class file named Student.cs and replace the template code with the following code.
[!code-csharpMain]
The ID
property will become the primary key column of the database table that corresponds to this class. By default, the Entity Framework interprets a property that's named ID
or classnameID
as the primary key.
The Enrollments
property is a navigation property. Navigation properties hold other entities that are related to this entity. In this case, the Enrollments
property of a Student entity
will hold all of the Enrollment
entities that are related to that Student
entity. In other words, if a given Student row in the database has two related Enrollment rows (rows that contain that student's primary key value in their StudentID foreign key column), that Student
entity's Enrollments
navigation property will contain those two Enrollment
entities.
If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection<T>
. You can specify ICollection<T>
or a type such as List<T>
or HashSet<T>
. If you specify ICollection<T>
, EF creates a HashSet<T>
collection by default.
The Enrollment entity
In the Models folder, create Enrollment.cs and replace the existing code with the following code:
[!code-csharpMain]
The EnrollmentID
property will be the primary key; this entity uses the classnameID
pattern instead of ID
by itself as you saw in the Student
entity. Ordinarily you would choose one pattern and use it throughout your data model. Here, the variation illustrates that you can use either pattern. In a later tutorial, you'll see how using ID without classname makes it easier to implement inheritance in the data model.
The Grade
property is an enum
. The question mark after the Grade
type declaration indicates that the Grade
property is nullable. A grade that's null is different from a zero grade -- null means a grade isn't known or hasn't been assigned yet.
The StudentID
property is a foreign key, and the corresponding navigation property is Student
. An Enrollment
entity is associated with one Student
entity, so the property can only hold a single Student
entity (unlike the Student.Enrollments
navigation property you saw earlier, which can hold multiple Enrollment
entities).
The CourseID
property is a foreign key, and the corresponding navigation property is Course
. An Enrollment
entity is associated with one Course
entity.
Entity Framework interprets a property as a foreign key property if it's named <navigation property name><primary key property name>
(for example, StudentID
for the Student
navigation property since the Student
entity's primary key is ID
). Foreign key properties can also be named simply <primary key property name>
(for example, CourseID
since the Course
entity's primary key is CourseID
).
The Course entity
In the Models folder, create Course.cs and replace the existing code with the following code:
[!code-csharpMain]
The Enrollments
property is a navigation property. A Course
entity can be related to any number of Enrollment
entities.
We'll say more about the DatabaseGenerated
attribute in a later tutorial in this series. Basically, this attribute lets you enter the primary key for the course rather than having the database generate it.
Create the Database Context
The main class that coordinates Entity Framework functionality for a given data model is the database context class. You create this class by deriving from the System.Data.Entity.DbContext
class. In your code you specify which entities are included in the data model. You can also customize certain Entity Framework behavior. In this project, the class is named SchoolContext
.
In the Data folder create a new class file named SchoolContext.cs, and replace the template code with the following code:
[!code-csharpMain]
This code creates a DbSet
property for each entity set. In Entity Framework terminology, an entity set typically corresponds to a database table, and an entity corresponds to a row in the table.
You could have omitted the DbSet<Enrollment>
and DbSet<Course>
statements and it would work the same. The Entity Framework would include them implicitly because the Student
entity references the Enrollment
entity and the Enrollment
entity references the Course
entity.
When the database is created, EF creates tables that have names the same as the DbSet
property names. Property names for collections are typically plural (Students rather than Student), but developers disagree about whether table names should be pluralized or not. For these tutorials you'll override the default behavior by specifying singular table names in the DbContext. To do that, add the following highlighted code after the last DbSet property.
[!code-csharpMain]
Register the context with dependency injection
ASP.NET Core implements dependency injection by default. Services (such as the EF database context) are registered with dependency injection during application startup. Components that require these services (such as MVC controllers) are provided these services via constructor parameters. You'll see the controller constructor code that gets a context instance later in this tutorial.
To register SchoolContext
as a service, open Startup.cs, and add the highlighted lines to the ConfigureServices
method.
[!code-csharpMain]
The name of the connection string is passed in to the context by calling a method on a DbContextOptionsBuilder
object. For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file. The connection string is highlighted in the following appsettings.json example.
The connection string created by the Visual Studio new-project template has a generated database name with a numeric suffix to guarantee uniqueness. You don't have to change that name.
SQL Server Express LocalDB
The connection string specifies a SQL Server LocalDB database. LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for application development, not production use. LocalDB starts on demand and runs in user mode, so there is no complex configuration. By default, LocalDB creates .mdf database files in the C:/Users/<user>
directory.
Add code to initialize the database with test data
The Entity Framework will create an empty database for you. In this section, you write a method that is called after the database is created in order to populate it with test data.
Here you'll use the EnsureCreated
method to automatically create the database. In a later tutorial you'll see how to handle model changes by using Code First Migrations to change the database schema instead of dropping and re-creating the database.
In the Data folder, create a new class file named DbInitializer.cs and replace the template code with the following code, which causes a database to be created when needed and loads test data into the new database.
[!code-csharpMain]
The code checks if there are any students in the database, and if not, it assumes the database is new and needs to be seeded with test data. It loads test data into arrays rather than List<T>
collections to optimize performance.
In Startup.cs, modify the Configure
method to call this seed method on application startup. First, add the context to the method signature so that ASP.NET dependency injection can provide it to your DbInitializer
class.
[!code-csharpMain]
Then call your DbInitializer.Initialize
method at the end of the Configure
method.
[!code-csharpMain]
Now the first time you run the application the database will be created and seeded with test data. Whenever you change your data model, you can delete the database, update your seed method, and start afresh with a new database the same way. In later tutorials you'll see how to modify the database when the data model changes, without deleting and re-creating it.
Create a controller and views
Next, you'll use the scaffolding engine in Visual Studio to add an MVC controller and views that will use EF to query and save data.
The automatic creation of CRUD action methods and views is known as scaffolding. Scaffolding differs from code generation in that the scaffolded code is a starting point that you can modify to suit your own requirements, whereas you typically don't modify generated code. When you need to customize generated code, you use partial classes or you regenerate the code when things change.
-
Right-click the Controllers folder in Solution Explorer and select Add > New Scaffolded Item.
-
In the Add Scaffold dialog box:
-
Select MVC controller with views, using Entity Framework.
-
Click Add.
-
-
In the Add Controller dialog box:
-
In Model class select Student.
-
In Data context class select SchoolContext.
-
Accept the default StudentsController.cs as the name.
-
Click Add.
-
When you click Add, the Visual Studio scaffolding engine creates a StudentsController.cs file and a set of views (.cshtml files) that work with the controller.
(The scaffolding engine can also create the database context for you if you don't create it manually first as you did earlier for this tutorial. You can specify a new context class in the Add Controller box by clicking the plus sign to the right of Data context class. Visual Studio will then create your DbContext
class as well as the controller and views.)
You'll notice that the controller takes a SchoolContext
as a constructor parameter.
[!code-csharpMain]
ASP.NET dependency injection will take care of passing an instance of SchoolContext
into the controller. You configured that in the Startup.cs file earlier.
The controller contains an Index
action method, which displays all students in the database. The method gets a list of students from the Students entity set by reading the Students
property of the database context instance:
[!code-csharpMain]
You'll learn about the asynchronous programming elements in this code later in the tutorial.
The Views/Students/Index.cshtml view displays this list in a table:
Press CTRL+F5 to run the project or choose Debug > Start Without Debugging from the menu.
Click the Students tab to see the test data that the DbInitializer.Initialize
method inserted. Depending on how narrow your browser window is, you'll see the Student
tab link at the top of the page or you'll have to click the navigation icon in the upper right corner to see the link.
View the Database
When you started the application, the DbInitializer.Initialize
method calls EnsureCreated
. EF saw that there was no database and so it created one, then the remainder of the Initialize
method code populated the database with data. You can use SQL Server Object Explorer (SSOX) to view the database in Visual Studio.
Close the browser.
If the SSOX window isn't already open, select it from the View menu in Visual Studio.
In SSOX, click (localdb)\MSSQLLocalDB > Databases, and then click the entry for the database name that is in the connection string in your appsettings.json file.
Expand the Tables node to see the tables in your database.
Right-click the Student table and click View Data to see the columns that were created and the rows that were inserted into the table.
The .mdf and .ldf database files are in the C:Users folder.
Because you're calling EnsureCreated
in the initializer method that runs on app start, you could now make a change to the Student class
, delete the database, run the application again, and the database would automatically be re-created to match your change. For example, if you add an EmailAddress
property to the Student
class, you'll see a new EmailAddress
column in the re-created table.
Conventions
The amount of code you had to write in order for the Entity Framework to be able to create a complete database for you is minimal because of the use of conventions, or assumptions that the Entity Framework makes.
-
The names of
DbSet
properties are used as table names. For entities not referenced by aDbSet
property, entity class names are used as table names. -
Entity property names are used for column names.
-
Entity properties that are named ID or classnameID are recognized as primary key properties.
-
A property is interpreted as a foreign key property if it's named (for example,
StudentID
for theStudent
navigation property since theStudent
entity's primary key isID
). Foreign key properties can also be named simply (for example,EnrollmentID
since theEnrollment
entity's primary key isEnrollmentID
).
Conventional behavior can be overridden. For example, you can explicitly specify table names, as you saw earlier in this tutorial. And you can set column names and set any property as primary key or foreign key, as you'll see in a later tutorial in this series.
Asynchronous code
Asynchronous programming is the default mode for ASP.NET Core and EF Core.
A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. When that happens, the server can't process new requests until the threads are freed up. With synchronous code, many threads may be tied up while they aren't actually doing any work because they're waiting for I/O to complete. With asynchronous code, when a process is waiting for I/O to complete, its thread is freed up for the server to use for processing other requests. As a result, asynchronous code enables server resources to be use more efficiently, and the server is enabled to handle more traffic without delays.
Asynchronous code does introduce a small amount of overhead at run time, but for low traffic situations the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.
In the following code, the async
keyword, Task<T>
return value, await
keyword, and ToListAsync
method make the code execute asynchronously.
[!code-csharpMain]
-
The
async
keyword tells the compiler to generate callbacks for parts of the method body and to automatically create theTask<IActionResult>
object that is returned. -
The return type
Task<IActionResult>
represents ongoing work with a result of typeIActionResult
. -
The
await
keyword causes the compiler to split the method into two parts. The first part ends with the operation that is started asynchronously. The second part is put into a callback method that is called when the operation completes. -
ToListAsync
is the asynchronous version of theToList
extension method.
Some things to be aware of when you are writing asynchronous code that uses the Entity Framework:
-
Only statements that cause queries or commands to be sent to the database are executed asynchronously. That includes, for example,
ToListAsync
,SingleOrDefaultAsync
, andSaveChangesAsync
. It does not include, for example, statements that just change anIQueryable
, such asvar students = *context.Students.Where(s => s.LastName = "Davolio")
. -
An EF context is not thread safe: don't try to do multiple operations in parallel. When you call any async EF method, always use the
await
keyword. -
If you want to take advantage of the performance benefits of async code, make sure that any library packages that you're using (such as for paging), also use async if they call any Entity Framework methods that cause queries to be sent to the database.
For more information about asynchronous programming in .NET, see Async Overview.
Summary
You've now created a simple application that uses the Entity Framework Core and SQL Server Express LocalDB to store and display data. In the following tutorial, you'll learn how to perform basic CRUD (create, read, update, delete) operations.
[!div class="step-by-step"] Next