Defining a Model (Using Entity Framework 7)

Recall that a model is the code used to interact with the data in your application. If you work with a database, this code typically returns a list of data or a single record. The code also supports user interaction on that data (create, update, and delete). If you already have a set of classes for working with your database and expressing your business logic, you can use them for your model. If you don’t have these classes, you need to create them.

As an example, imagine that you have a database that contains a Customers table. You could write a custom class to express the properties and validation rules of a Customer object. You might also write functionality to get a list of customers, read a single customer, update a customer in the database, and more. Alternatively, you can let the Entity Framework handle much of this work on your behalf. This saves you from writing the data access, update, storage, and delete code from scratch. In this example, we use the Entity Framework 7 Code First. (See Chapter 13 for more details on working with databases.)

Creating a Simple Class

With Code First, you write very little code, and you do not have a bunch of generated code in your solution. Instead, you write plain old CLR objects (POCOs) classes to represent your model. These classes define objects, properties, and business rules. The database access is taken care of for you with Entity Framework. The following walks you through building the Customer model.

1. Start by creating a new project (File, New Project) based on the ASP.NET 5 Web Site template (or, if you’ve been following along, you can use the project you’ve already created for the other examples earlier in the chapter).

The examples assume your site is named, AspNet5AppSample. This name is used in the namespace definitions for class files.

2. Inside Visual Studio Solution Explorer, right-click the Models folder and choose Add, New Item. Select the Class template from the Add New Item dialog. Name the class Customer.cs.

3. Create the properties to represent a simple Customer instance. Listing 17.4 shows an example.

LISTING 17.4 The Customer.cs POCO Model Class


using System;

namespace AspNet5AppSample.Models
{
  public class Customer
  {
    public int Id { get; set; }

    public string Name { get; set; }

    public string Email { get; set; }

    public bool OptInEmail { get; set; }

    public string Notes { get; set; }
  }
}


Adding Model Validation Rules

ASP.NET includes support for data annotations. A data annotation is metadata that you assign to the properties of your class using data attributes. This metadata is then interpreted by ASP.NET at runtime as validation rules for the properties in your class. For example, you might annotate a property with the RequiredAttribute. ASP.NET will then validate your model both on the client (using JavaScript) and on the server. If the model state is not valid, the object is not valid and the user should be notified.

The data attributes are found in the System.ComponentModel.DataAnnotations namespace. There are dozens of attribute classes available to you. However, the following provides an overview of many of the common data attribute classes. (The word Attribute is omitted from the class name for clarity.)

Image Association—Used to indicate the property works as a data relationship (or foreign key).

Image Compare—Used to compare the values of two properties (such as password and password match).

Image CreditCard—Used to indicate that a given property should be a credit card number.

Image DataType—Used to mark a property as a specific data type. This is useful if the actual type you intend is different from the one stored in your database. For example, you may have a PostalCode property you store as a string in the database but want to validate it as numeric.

Image Editable—Used to indicate if a given property should be allowed to be changed by a user. You can use this attribute to mark a property read only or allow an initial value.

Image Email—Validates a property as containing an email address.

Image Key—Used to indicate if a property represents a primary key for the item.

Image MinLength, MaxLength—Used to validate against a min or max length of a property that represents a string or array.

Image Phone—Validates a given property contains a valid phone number.

Image Range—Used to validate against an allowable numeric range for the property.

Image RegularExpression—Allows you to write a regular expression against which the property should be validated.

Image Required—Used to mark a property as requiring a value.

Image StringLength—Used to set the min and max length of characters in a property of type string.

Image Url—Validates a property as a URL.

The attribute classes just listed all work in a similar way. You use them to annotate properties of your object. A simple validation attribute will require no additional configuration and will include a default message to be displayed when the validation fails. However, some data annotation attributes require additional configuration to work properly, such as setting the maximumLength on StringLength. Each attribute also includes the ErrorMessage property that allows you to set a custom error message if validation fails.

Let’s add a few data annotations to the Customer class created previously. The following walks you through this process:

1. Add a using statement at the top of Customer.cs for System.ComponentModel.DataAnnotations.

2. Annotate the Name property with the Required attribute.

3. Add both the Required and the EmailAddress to the Email property. You can do so by separating them with a comma.

Configure the ErrorMessage property for the EmailAddress attribute to set a custom message to be displayed when the property is not valid.

4. Mark the Id property with the Key attribute to indicate this is the primary key for the object.

5. Constrain the Notes property using StringLength. Set the maximumLength to 250.

Listing 17.5 shows an example of what your model should now look like following the addition of these data annotations.

LISTING 17.5 The Customer.cs Model with Data Annotations


using System;
using System.ComponentModel.DataAnnotations;

namespace AspNet5AppSample.Models
{
  public class Customer
  {
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required, EmailAddress(
      ErrorMessage ="Please use email format, [email protected]")]
    public string Email { get; set; }

    public bool OptInEmail { get; set; }

    [StringLength(maximumLength:250)]
    public string Notes { get; set; }
  }
}


ASP.NET will use these data annotations to execute validation on the client (using the jQuery.validate plug-in). They will also be part of the model state validation on the server (inside your controller). You will see these in action later in the chapter as we round out this sample.

Creating the Data Context

The next step with Entity Framework 7 (EF7) is to create a database context class that derives from Microsoft.Data.Entity.DbContext. Entity Framework uses the database context class to get enough information about your objects so it can work with the entities in your database. You can do a lot with DbContext and related Entity Framework code (including handling object to data entity migrations/updates). However, this example simply uses this approach for writing Customer objects to a database.

Recall that EF7, like ASP.NET Core 5, is now modular. The project template in our sample already includes a reference to EF7 for SQL Server. You can open the project.json file to see this ("EntityFramework.SqlServer": "7.0.0-beta4"). You could replace this, for example, with SQLite using NuGet and installing EntityFramework.SQLite. For our example, however, we will stick to the SQL Server version. The following walks you through this process of creating the DbContext object:

1. Add a class to the Models folder called CustomerDbContext.cs. To do so, right-click the Models folder in Solution Explorer and choose Add, New Item. Select the Class template.

2. Add a using statement at the top of the class for Microsoft.Data.Entity.

3. Update the CustomerDbContext class definition to inherit from DbContext.

4. Create a public property of type DbSet<Customer> called Customers.

Listing 17.6 shows the new CustomerDbContext class.

LISTING 17.6 The Data Context Class


using System;
using Microsoft.Data.Entity;

namespace AspNet5AppSample.Models
{
  public class CustomerDbContext : DbContext
  {
    public DbSet<Customer> Customers { get; set; }
  }
}


Connecting to the Database

Of course, we need a database with which to work. EF7 supports working with an existing database or using the tools to create one based on your model. In past versions of the Entity Framework, you could simply run your application; if EF did not find the database, it automatically created one for you. However, this database generation at project runtime was problematic and difficult to keep in synch beyond the initial database generation. EF7 addresses these issues. You no longer get a database just by running some code. Instead, you can use console commands to generate a database migration script based on your model. You can then execute that script to create your database. These migration scripts are code files stored in the Migrations folder of an ASP.NET MVC project. You can use these files to keep your database and model in sync during development and deployments.

To get started, we will define a connection string for working with the database. There are many places we can put the database connection. For this example, we will use the config.json file for storing a database connection string for our project. The following walks you through the process:

1. Open the config.json file from Solution Explorer. Notice there is already a Data group with a DefaultConnection item. This was created by the template for working with the ASP.NET user profile and membership services.

In the example, however, we plan to store membership data and application data in the same database. Therefore, edit the connection in the file to point at a new database named AspNet5Unleashed. (Database=AspNet5Unleashed). We will generate this database in a moment.

Note that you may also have to change your server name in the connection string depending on your installation. To get your server name, open SQL Server Object Explorer in Visual Studio (View, SQL Server Object Explorer). Your local database server should show in the tree (along with its name).

You can also right-click the server and choose Properties. Here you can find the “Connection string” property to use as a guide. For example, you can use the first section, Data Source=(localdb)\ProjectsV12; to get the server name, (localdb)\ProjectsV12 and update the default connection string to Server=(localdb)\ProjectsV12;.

When complete, your connection string should look similar to the one shown at the top of Figure 17.20.

Image

FIGURE 17.20 Create a database connection string inside config.json.

2. Now open Startup.cs from Solution Explorer. Recall that this is where you configure the ASP.NET request pipeline. Navigate to the ConfigureServices method.

You should see a call to services.AddEntityFramework(). There are methods on this object that use dependency injection to add additional dependent services at runtime. Use this call to add registration for the CustomerDbContext instance as shown here.

services.AddEntityFramework()
  .AddSqlServer()
  .AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(Configuration
      ["Data:DefaultConnection:ConnectionString"]))
  .AddDbContext<CustomerDbContext>(options =>
          options.UseSqlServer(Configuration
      ["Data:DefaultConnection:ConnectionString"]));

Creating the Database Using EF7 Migrations

Now that you have defined a connection to the database, you need to actually create the database. You can do so manually using SQL Server Object Explorer. You can also use the EF7 migration commands in Visual Studio to generate your database from your model. You will see an example of both scenarios. Some developers like to use the SQL tools and create the database manually. Others prefer to keep their database in synch with their models using tools.

Let’s start by looking at how you would automate database schema updates using EF migration. To do so, you will use commands that are part of the EntityFramework.Commands package installed by the default template. You can see this package in the References folder in Solution Explorer and in project.json. In the latter, these commands get mapped to the ef variable. You will use this in the command window to generate a migration file and execute it.

The Commands package makes working with data migrations (object to entity mapping) easier. However, this NuGet package is optional; you do not need to use it. In addition, there is no need to deploy it once you are done doing development. Instead, you can set the package as a dev-time dependency.

Visual Studio also includes tools called the DNVM (.NET Version Manager) and DNU (.NET Development Utility). These are command-line tools that uses the EntityFramework.Commands package to help you generate code for a migration based on your model. The following walks you through creating the database from your models using commands from these tools:


Note

The EF7 code was in beta (beta 4) at the time of writing. In addition, the supporting tools were also in development. This section walks you through what was available at the time of writing: the command line approach to creating and applying a migration based on your model. However, it is possible the tooling will also be integrated directly into the Visual Studio IDE. That said, this command line approach should still operate as outlined.


1. Open the Developer Command Prompt for VS2015 (Windows Start, Developer Command Prompt for VS 2015). This opens a command window setup to work with Visual Studio command line tools.

2. To get started, you need to change the active directory in the command prompt to folder that contains your project.json file. In our example, you use the cd command to navigate to the project folder. You then use the following to get to the folder containing project.json:

cd .srcaspnet5appSample

3. Next, you need to use DNVM to add a .NET runtime for use by the command window. You can do so using the use command. To see a list of available runtimes, type dnvm list. To bind a runtime to the path, use the following command at the prompt (where your version number matches that found in the dnvm list):

dnvm use 1.0.0-beta4 coreclr

4. You may also have to use the DNU to restore NuGet packages before continuing. You can do so using the following command:

dnu restore

5. You are now ready to execute a command to create an EF7 migration. You do so using the DNX tool and the ef command. The ef command is defined inside project.json under Commands to point to EntityFramework.Commands.

The first step is to generate migration code based on your data context object. The following command does so. You can see that we name the migration InitialSchema; the migration class will contain this name. We also explicitly indicate which class (CustomerDbContext) we want to use as a basis for the generated migration code (as there may be more than one in your project).

dnx . ef migration add InitialSchema -c CustomerDbContext

6. Upon success, return to Visual Studio and navigate to the Migrations folder for your project. You should now have two new files in the folder: one that ends with the name, _InitialSchema.cs; and another with the name, CustomerDbContextModelSnapshot.cs.

7. The DNX tool will use these classes to apply this migration to your database. The database connection will be gleaned from your project file, config.json. Enter the following apply command inside the command window.

dnx . ef migration apply -c CustomerDbContext

You can now return to Visual Studio and open the database (View, SQL Server Object Explorer). You may have to use the refresh button on the tool pane window. You should then see the AspNet5Unleashed database and the dbo.Customer table.

This EF7 migration method can be used to keep your model and database in synch. As you make changes to the model, you can use the commands discussed here to create migration scripts. You can then apply these scripts as required to various environments in order to deploy your database changes.

Creating the Database Manually

Some developers prefer to create the database manually using script or the tools themselves to generate script. Visual Studio and EF7 support this scenario. The following walks you through creating the database manually using Visual Studio:

1. Open SQL Server Object Explorer from the View menu; navigate to your database and the Databases folder.

Right-click the Databases folder and choose Add New Database. Name the database AspNet5Unleashed.

2. Expand the node that represents your newly created database. Navigate to the Tables folder and right-click it. Select Add New Table.

3. Use the table designer to create fields for the Customers table. Use the T-SQL script editor to change the name of the table to Customer (singular).

Figure 17.21 shows an example of what your table should look like.

Image

FIGURE 17.21 Use the database tools to create the AspNet5Unleashed database and the Customer table.

4. Right-click the Id property and choose Properties. Set this primary key as an Identity column with an Identity Seed of 1 and an Identity Increment of 1. See the right side of Figure 17.21 as an example.

5. Click the Update button on the table designer to update the database. This brings up the Preview Database Updates dialog. If all looks right, click the Update Database button to submit your changes. You should see the changes as they are being made inside the Data Tools Operations window. Note that Visual Studio will ask you if you want to save the .sql script file. This is not necessary for most workflows as you can always regenerate this if necessary.

You should now have a database, a data context class, and a class that represents your data model. Entity Framework should also now be configured to connect to and work with your database. The next step is to write a controller for handling requests for customer data and views.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset