Add Model
There are three ways to approach Entity Framework:
There are three ways to use the Entity Framework:
Database-first: You start with a database, and Entity Framework generates the code.
Database-first (Database first): starts from a Database, and then the Entity Framework generates the corresponding code.
Model-first: You start with a visual model, and Entity Framework generates both the database and code.
Model-first: starts with a visual Model, and then the Entity Framework generates databases and code.
Code-first: You start with code, and Entity Framework generates the database.
Code-first: starts from the Code, and then the Entity Framework generates a database.
We are using the code-first approach, so we start by defining our domain objects as POCOs (plain-old CLR objects ). with the code-first approach, domain objects don't need any extra code to support the database layer, such as transactions or persistence. (Specifically, they do not need to inherit from the EntityObject class .) you can still use data annotations to control how Entity Framework creates the database schema.
We plan to use the code-first method. Therefore, we first define the domain object as a POCO (plain-old CLR objects-Legacy Common Language Runtime (CLR) object. Many people do not quite understand POCO objects. In fact, such objects are just like text files and are the simplest, most primitive objects without any format. Therefore, it is easier to process such objects in various environments, including processing in various languages-Translator's note ). Using the code-first method, the domain object does not need any additional code to support the database layer, such as transaction processing and persistence. (In particular, they do not need to inherit from the EntityObject class .) You can still use data annotation to control how the Entity Framework creates a database solution.
Because POCOs do not carry any extra properties that describe database state, they can easily be serialized to JSON or XML. however, that does not mean you shoshould always expose your Entity Framework models directly to clients, as we'll see later in the tutorial.
Since POCO does not include any additional attributes that describe the database status, they can be easily serialized into JSON or XML. However, this does not mean that you should always expose the Entity Framework model directly to the client, as we will see later in this tutorial.
We will create the following POCOs:
We will create the following POCO:
Product
Order
OrderDetail
To create each class, right-click the Models folder in Solution Explorer. From the context menu, select Add and then select Class.
To create each class, right-click the Models folder in Solution Explorer. Select "add" from the context menu, and then select "class" (2-14 ).
Figure 2-14. Create a POCO class
Add a Product class with the following implementation:
Use the following implementation to add a Product class ):
Copy codeThe Code is as follows:
Namespace ProductStore. Models
{
Using System. ComponentModel. DataAnnotations;
Public class Product
{
[ScaffoldColumn (false)]
Public int Id {get; set ;}
[Required]
Public string Name {get; set ;}
Public decimal Price {get; set ;}
Public decimal ActualCost {get; set ;}
}
}
By convention, Entity Framework uses the Id property as the primary key and maps it to an identity column in the database table. when you create a new Product instance, you won't set a value for Id, because the database generates the value.
According to the Conventions, the Entity Framework uses the Id attribute as the primary key and maps it to the Id column in the database table. When creating a new Product instance, you do not need to set a value for the Id because the database generates it.
The ScaffoldColumn attribute tells ASP. net mvc to skip the Id property when generating an editor form. the Required attribute is used to validate the model. it specifies that the Name property must be a non-empty string.
The ScaffoldColumn annotation property tells ASP. net mvc to skip this Id attribute when generating and editing a form. The Required annotation attribute is used to verify the model. It specifies that the Name attribute must be a non-empty string.
Note: In this article, attributes of the English class ScaffoldConlumn and Required called Annotation Attribute are translated into Annotation attributes to distinguish them from those in the class.
Add the Order class:
Add Order class ):
Copy codeThe Code is as follows:
Namespace ProductStore. Models
{
Using System. Collections. Generic;
Using System. ComponentModel. DataAnnotations;
Public class Order
{
Public int Id {get; set ;}
[Required]
Public string Customer {get; set ;}
// Navigation property
// Navigation attributes
Public ICollection <OrderDetail> OrderDetails {get; set ;}
}
}
Add the OrderDetail class:
Add OrderDetail class (Order details class, or order details class ):
Copy codeThe Code is as follows:
Namespace ProductStore. Models
{
Public class OrderDetail
{
Public int Id {get; set ;}
Public int Quantity {get; set ;}
Public int OrderId {get; set ;}
Public int ProductId {get; set ;}
// Navigation properties
Public Product {get; set ;}
Public Order {get; set ;}
}
}
Foreign Key Relations
Foreign key relationship
An order contains limit order details, and each order detail refers to a single product. to represent these relations, the OrderDetail class defines properties named OrderId and ProductId. entity Framework will infer that these properties represent foreign keys, and will add foreign-key constraints to the database.
An order contains many order details, and each order details point to a single product. To represent these relationships, the OrderDetail class defines the attributes named OrderId and ProductId. The Entity Framework will infer that these attributes represent foreign keys and add foreign key constraints to the database (see Figure 2-15 ).
Figure 2-15. Foreign key relationship
The Order and OrderDetail classes also include "navigation" properties, which contain references to the related objects. Given an order, you can navigate to the products in the order by following the navigation properties.
The Order and OrderDetail classes also contain the "navigation" attribute, which contains references to related objects. For a given order, you can navigate to the product of this Order Based on the navigation attributes.
Compile the project now. Entity Framework uses reflection to discover the properties of the models, so it requires a compiled assembly to create the database schema.
Compile the project. The Entity Framework uses reflection to discover the attributes of these models, therefore, it requires the compiled Assembly to create the corresponding database scheme (the Database Scheme here refers to the definition of the database, table structure, and relational database-Translator's note ).
Configure the Media-Type Formatters
Configure the Media-Type formatter
A media-type formatter is an object that serializes your data when Web API writes the HTTP response body. the built-in formatters support JSON and XML output. by default, both of these formatters serialize all objects by value.
Media-type is an object serialized when an HTTP response body is written by a Web API. The built-in formatter supports JSON and XML output. By default, both formats serialize all objects by value.
Serialization by value creates a problem if an object graph contains circular references. that's exactly the case with the Order and OrderDetail classes, because each holds a reference to the other. the formatter will follow the references, writing each object by value, and go in circles. therefore, we need to change the default behavior.
If the object graph contains a circular reference, value-based serialization may cause problems. This is exactly the case of the Order class and OrderDetail class, because each one contains a reference to another. The formatter will follow these references and write every object by value, which will lead to a loop. Therefore, we need to modify this default behavior.
In Solution Explorer, expand the App_Start folder and open the file named WebApiConfig. cs. Add the following code to the WebApiConfig class:
In Solution Explorer, expand the App_Start folder and open the file WebApiConfig. cs. Add the following code to the WebApiConfig. cs class ("New Code"-Translator's note in the following code ):
Copy codeThe Code is as follows:
Public static class WebApiConfig
{
Public static void Register (HttpConfiguration config)
{
Config. Routes. MapHttpRoute (
Name: "DefaultApi ",
RouteTemplate: "api/{controller}/{id }",
Defaults: new {id = RouteParameter. Optional}
);
// New code:
// New code:
Var json = config. Formatters. JsonFormatter;
Json. SerializerSettings. PreserveReferencesHandling =
Newtonsoft. Json. PreserveReferencesHandling. Objects;
Config. Formatters. Remove (config. Formatters. XmlFormatter );
}
}
This code sets the JSON formatter to preserve object references, and removes the XML formatter from the pipeline entirely. (You can configure the XML formatter to preserve object references, but it's a little more work, and we only need JSON for this application. for more information, see Handling Circular Object References .)
This Code sets the JSON formatter to prevent object reference (the second line of "New Code"-Translator's note ), and the XML formatter is completely deleted from the pipeline (HTTP request processing pipeline-Translator's note) (The role of the last line of "New Code"-Translator's note ). (You can also configure the XML formatter to prevent object reference, but this requires some work. For this application, we only need JSON. For more information, see "processing cyclic object references"