[Original address] Code-first development with Entity Framework 4
. Net 4 is accompanied by the release of an Entity Framework (EF)-a data access function library located in the system. Data. entity namespace.
When Entity Framework was first released in. Net 3.5 SP1, many programmers gave us feedback about what they thought was insufficient in the first version. The SQL team listened to these opinions and learned from. Net 4.
Major improvements in EF4 include:
·Supports Simple CLR objects (POCO): Now you can define entities without the need for base classes or data persistence attributes.
·Support for delayed Loading: Now you can load sub-objects in real time instead of pre-load them.
·Supports N-Layer Technology and self-tracking entities: It is used to process the transfer of objects between layers or Stateless web calls.
·Better support for SQL statement generation and stored procedures: EF 4 executes faster SQL statements and supports better storage process integration.
·Supports automatic singular and plural nouns Conversion: EF4 supports automatic conversion of single and multiple numbers of table names (for example, categories-> category ).
·Better Testability: In EF4, it is now easier to create simulated objects based on interfaces.
·Supports more LINQ Operators: EF4 now supports all the operators in the LINQ clause.
Visual Studio 2010 also provides richer ef-specific designers and tools. The EF designer of vs 2010 also supports the "database-first" development mode-creating a model layer on the design interface through existing databases. And the development mode that supports "model first"-that is, you define the model layer on the design interface, and then generate the database structure based on it.
Use EF for code priority development
In addition to the development process based on the designer, EF 4 also supports a code-centric development solution, which we call "code-first development ". Code-first development opens a beautiful development process. It allows you:
· You can develop programs without opening the designer or defining an XML ing file.
· You only need to write a simple class to define the model object, instead of having any base class.
· Use the "Convention above configuration" method to achieve database persistence without explicitly configuring anything.
· You can also selectively rewrite persistence based on conventions, and provide a smoother API to completely customize the persistence ing.
To use EF's "code-first Development" concept, You need to download an additional tool running on. NET 4 built-in EF. The CTP 4 version of the "code first" function library was released this week. You can download it from here.
You can use it in any. Net 4 Project in vs 2010 (including ASP. NET web forms project and ASP. net mvc ).
Hands-on Tutorial: use the code-first method to create a nerddinner
Last year I wrote a tutorial on ASP. NET MVC 1.0, published in my blog and book. This tutorial explains how to create a simple program called "nerddinner", which facilitates online organization, hosting, and participation in a meal meeting. You can refer to my original ASP. NET V1 nerddinner tutorial here. The new book ASP. net mvc 2 advanced programming also contains updated tutorials.
In this nerddinner tutorial, we used the "database first" method, that is, to pre-define the database structure, then, you can use the visual stduio designer to create model objects such as LINQ to SQL or LINQ to entities for ing.
Next, I will demonstrate how to use the "code first" method of EF 4 to create the nerddinner model layer and database structure, and then use ASP. NET MVC to create an add, delete, modify, and query program.
We will create this program step by step. At the end of this article, we will download the complete sample code.
Step 1: Create an empty ASP. net mvc 2 Program
Create an ASP. net MVC 2 project start, select File-> new project and use "ASP. net MVC 2 empty Web Application Project template.
In this way, an empty ASP. net mvc 2 project will be created, with no controllers, models, and views in it.
In the next step, we will define the nerddinner "model", which indicates the data objects in the program and the logic including the verification mechanism and business rules. The model is based on the "Heart" of the MVC program and actually controls the behavior of the program. We will use EF 4's new "code first" method to create this model layer.
Step 2: create a model
Now let's assume that we haven't created a database, and create the nerddinner program from the beginning.
We do not need to start from the database
When the code-first development process is used, you do not need to create a database or define a database structure to start program development. Instead, we can start by defining the standard. Net class that best fits the model objects of our program-avoiding the troubles of the hybrid data persistence logic in it.
Create model type
Nerddinner is a small program and the data storage required is very simple. We want to define and store events that represent people's participation-"dinners )". We also want to define and store the "RSVP" people who participate in the banquet to track people who are interested in the specific banquet.
Let's create two classes (dinner and RSVP) to express this concept. In our ASP. net mvc project, add two classes-"dinner" and "RSVP:
The above "dinner" and "RSVP" Model classes are "simple CLR objects" (that is, POCO ). They do not need to inherit any base classes or implement any interfaces, and all the attributes defined in them are standard. NET data types. No code is added to the data persistence attribute and operation data.
When defining model classes, you do not need to bind them to a specific database, database API, and database structure. This is indeed very powerful-and gives us a more flexible way to access data. In this way, we can focus on the program and business needs, without having to think too much about the implementation method of persistence. In addition, it also provides us with an elastic space to replace the database structure or storage implementation-code that does not need to override model objects or interact with them.
Create a context class to process data persistence
We have already defined two poco model classes. Now let's create a class to process the work of obtaining or saving dinner And rsvp instances in the database.
We name this class "nerddinners ". It inherits from the dbcontext base class and defines two public attributes-one for exposing the dinner object set and the other for exposing the RSVP object set:
The dbcontext and dbset classes used above are provided by the EF 4 Code priority function library. You need to add a reference to the system. Data. entity. CTP assembly, which is located in the \ Program Files \ microsoft ADO. NET Entity Framework feature ctp4 \ binaries directory. In addition, in the "nerddinners" type definition file, you need to add a reference to the "using system. Data. Entity" namespace.
This is all the code we need to write.
The above three classes are all the code required to implement a basic model and data persistence layer for our nerddinner program. We do not need to configure additional image injection information for the database structure, and do not need to run any tools or write any XML files, no designer is required to use our classes to retrieve, update, and store data in the database.
Convention-based persistent projection
No additional code is required, no XML files need to be created, and no tools are required to map our model classes in the database. You may ask, is this possible?
By default, the EF code priority Database supports a "Convention is higher than configuration" method, which uses common ing habits to avoid explicit configuration. If you want to use custom database ing rules, you can repeat these conventions. However, if you use the Convention, you will find that you need to write very little code, without the need to add additional code and configuration, 90% of common cases can work normally.
In the preceding example, the nerddinner context class maps the "dinners" and "RSVPs" attributes to the "dinners" and "RSVPs" Data Tables of the database by default. Each row in the "dinners" table is mapped to an instance of the "dinner" type. Of course, each row in the "RSVPs" table is mapped to an instance of the "RSVP" type. Attributes of the "dinner" and "RSVP" types are mapped to columns in the "dinners" and "RSVPs" tables.
Other conventions supported by EF include automatic identification of primary keys and Foreign keys through common naming modes (for example, primary keys can be inferred based on the ID or dinnerid attribute in the dinner class ). EF also cleverly supports the practice of binding associations between two models. Here is a blog by the EF team explaining the supported default practices.
Sample Code using our model
The three classes we created earlier contain all the classes that implement the nerddinner model and data persistence.All code. Now let's take a look at some code examples to see how to use these classes to perform common database operations:
Execute a query using a LINQ expression
Use the following LINQ query expression to obtain data from the database. Use a LINQ expression to obtain all the meals to be held:
We can also use the relationship between dinners and RSVPs when writing a LINQ expression. Pay attention to the "where" clause to filter out the way in which the number of participants is greater than 0:
Note that the "where" clause of the preceding query (that is, to obtain at least one member of the banquet) is executed on the server side-to make the query and loading data more efficient.
Get an instance
We can use the single () function of LINQ and the Lamda query to obtain an instance of dinner, as shown in the following code:
Alternatively, we can use the find () function provided by the EF "code first" function library to load an instance based on the ID:
Hold new banquet
The following code demonstrates how to create a new dinner instance and add it to the database. All we need to do is "new" A Dinner object, set its attributes, and add it to the dinners attribute of the nerddinner context object. The nerddinner context class supports the "unit of work" mode, that is, you can add multiple models in the context, and then call "savechanges ()" to save all database changes in transaction mode.
Update meeting Information
The following code demonstrates how to obtain a dinner instance, update one of the attributes, and save the changes to the database:
Step 3: Create an ASP. net mvc controller that uses our model
Now let's take a look at the more complete scenario of using the model, use a controller type to publish the upcoming banquet list, and allow users to add new banquets:
Right-click the "controllers" folder and select the "Add-> controller" menu item. we name the new controller "homecontroller ".
Then, add three "Action functions" to process the nerddinners model created using the EF "code first" function library:
.
The "Index" Action Function loads and displays the list of upcoming meals.
The "CREATE" Action function allows users to publish new meals. The first "CREATE" function is used to process the "http get" scenario when a user accesses the/home/create page and sends a "new dinner" form for the user to fill in. The second "CREATE" function is used to process the "http post" scenario associated with the form-saving the new meal information to the database. If there is any verification error, it will re-display the form and add the corresponding error message.
Add a view to our Controller
The next step is to add two "view templates" to the project-one for "Index" and the other for "CREATE ".
Place the cursor in the index function of the Controller to add a View to the project. Right-click the view and choose "add view" from the context menu. The "add view" dialog box is displayed. We will create a strongly typed view, and then pass it into an ienumerable list containing the "dinner" model object:
After you click Add, Visual Studio creates/Views/home/index. aspxFile. Add the following code to generate a <ul> list for the meeting Information and display the link for creating the meeting:
Place the cursor in the create function of the controller to add the "Create" View to the project, and right-click the "add view" command in the menu. In the "add view" dialog box, we still specify to create a strong-type view and pass it a dinner object. In addition, we want to use the "Create" template to build a framework:
After you click Add, Visual Studio creates/Views/home/create. aspxFile, which contains a draft HTML <form> form generated for the "dinner" object. We made some adjustments and deleted the input element generated for the dinnerid attribute. The final view template is as follows:
So far, we have written all the code on the website for listing and creating meal information controllers and views.
Step 4: Database
The Code has been written. Now let's run the program.
But what about databases?
We do not have a database yet-in fact, it is not necessary so far, because our "code first" development process does not require the database to define and use our model classes.
But when we actually run our application, we need to store dinner And rsvp objects. We can use one of the following two methods to create a database:
1. Use Database tools (such as SQL management studio or Visual Studio) to manually create and define database structures;
2. Use the EF code priority class library to automatically create and generate database structures based on the defined model.
The second method is cool, and we need to use it in our nerddinner program.
Configure the database connection string
Before starting, set the connection string pointing to the database to be created. We add the database connection string "nerddinners" to the Web. config file of the application, as shown below:
By default, when you use the EF code priority class library to create a dbcontext class, it will automatically find the connection string that matches the context class name. Because we name the context class "nerddinners", when the ASP. NET application initializes it, the previously added "nerddinners" database connection string will be found by default.
Use SQL Ce 4
The EF code priority Class Library supports multiple different databases, including SQL Server, SQL Express, and MySQL.
Two weeks ago, I wrote a blog about using the embedded SQL Ce 4 database engine in ASP. NET. SQL Ce 4 is a lightweight file-based database that is easy to install and can be embedded in ASP. NET applications. It supports a low-cost host environment and easily migrates data to the SQL Server database.
In the early stages of defining (and redefining) Your Data Model layer, SQL CE can be a good choice-In addition, you can quickly create and recreate databases as long as you want. When developing the nerddinner application, we use SQL Ce 4 as the database. Later, we can choose to change the connection string to deploy the product to SQL express or SQL Server-no need to modify any line of code.
The database connection string I set earlier specifies the nerddinners. SDF database file and uses the SQL Ce 4 database driver. To make it work properly, you also need to install SQL Ce 4-install it through the standard SQL ce installer or webmatrix (with built-in SQL CE ). SQL Ce 4 is very small and can be installed in just a few seconds.
Important :In the above connection string, we specify the nerddinners. the SDF file is created in the \ datadirectory \ folder -- in ASP.. NET application corresponds to the \ app_data \ folder under its root directory. By default, this directory is not created when the "Empty ASP. net mvc web application" Project template is created. Therefore, you need to create this folder explicitly in the project (right-click the project and choose "add ASP. NET folder-> add_data->" menu item ).
Automatically create a database schema)
The EF code priority Class Library supports the ability to automatically generate database structures and databases from the data model class-eliminating the need to manually perform these steps.
If the SQL ce or SQL express database file specified by your connection string is inDisk does not exist,DefaultThis will happen. You do not need to perform any manual steps at all.
To see the effect, press F5 to run our nerddinner application. It starts the browser and accesses the root directory of our application "/". You can see the following picture:
Accessing the root directory of the application will call the homecontroller. Index () function-it will instantiate and query our nerddinners context class to obtain the list of upcoming meals from the database. Because the nerddinners. SDF database file specified in the connection string does not exist, the EF code priority class library will automatically create the database for us. It will deduce the database structure based on the nerddinners context class, and finally generate the database.
You can click the "show all files" icon in the Visual Studio solution manager, and then click the "refresh" button to expand the app_data folder to view the automatically generated SQL ce database file.
In the future, we will release an update package for vs 2010. You will be able to open and edit the SQL Ce 4 database on the "server resource manager" (just like editing the SQL database now ). In this way, you can easily see (or make some adjustments) the database structure and data content. At that time, you can also use the database tool in webmatrix to view the content of the SQL Ce 4 database file.
We have not specified any custom data persistence ing rules for the nerddinners data class. Therefore, the EF code priority class library will automatically generate a database based on the default naming rules. However, if we specify any custom ing rules, the EF code priority class library will follow these rules to generate databases that match them.
Let's review the two poco Data Model classes and the nerddinners context class we previously defined:
The following are two tables in the database automatically created based on the above model class after we run the application.
Shows the definitions of the "dinners" table. The column name exactly corresponds to its data type and the attributes defined in the dinner class. The dinnerid column is automatically set to the primary key and unique ID column of the table.
Shows the definition of the "RSVPs" table. The column name of the table and its data type are consistent with the attributes defined in the RSVP class. The rsvpid column is set as the primary key and unique ID column of the table.
Between the dinners table and the RSVPs table, a one-to-many primary key/foreign key relationship is also created. The EF code priority class library automatically establishes this association, because the dinner class has a RSVPs attribute of the icollection <RSVP> type, and the RSVP class also has a dinner attribute.
Fill in meeting information for the database
Now, let's create some meeting Information and write them into the database. You can click the "Create new dinner" link on our homepage to go to the "new" page.
When we click "CREATE", the new meal will be saved to the database. We can repeat several times to create multiple meals. Each newly created meeting will be saved in the database and displayed in the "Upcoming dinners" list on the homepage.
Step 5: change the data model
With the development of our applications, we will continue to improve and reconstruct our models. The EF code priority class library includes some good development functions, which makes it easier for us to coordinate some improvements when developing databases.
Add a new attribute to the dinner Model
Let's make a simple modification to our dinner class. More specifically, we will add a new "country" attribute to the dinner class.
After completing the changes, let's press the F5 button in virtual studio to re-compile and run the application. The following error message is displayed:
These error messages occur because we modified the structure definition of the dinner class and our model object is no longer consistent with the automatically created dinners table in the database.
When EF automatically creates a database for you, an "edmmetadata" table is added by default. This table is used to record the shape of the model object used for automatic database creation.
When EF finds that you have modified the model object and are not synchronized with the database that was created automatically, the above error message is displayed.
Re-Synchronize the data model class to the database
We have many ways to synchronize model images and databases:
- We can manually update the schema in the database to make them consistent.
- You can also delete the database file and run the application again so that EF can automatically recreate the database.
- You can also enable the EF code priority function to automatically update the database when any data model changes.
Next, let's look at how to use the last automatic update method in the nerddinner application.
Recreatedatabaseifmodelchanges
This includes a very usefulDevelopment Time(Development-timeFunction, which allows you to modify the data model class at any time and automatically rebuild the database. When you enable this function, EF can identify when the class model used to create a database is changed, when can your database be rebuilt to match the new model class-you do not need to perform any manual operations.
This feature is particularly useful when you are developing an application, because it brings a lot of freedom and flexibility for you to quickly refactor your model code-you don't have to manually synchronize the database structure. It is especially suitable for SQL ce, because SQL CE is a file-based database and can be deleted and created at runtime at any time. This makes the development process incredibly smooth.
The simplest way to enable this function is to add the database. setinitializer () method call to the application_start () event processing function in the global. asax class.
This call Tells EF to reconstruct the nerddinners. SDF database to match the nerddinners class when the data model changes. Now, when we re-run the application, there will no longer be any error message indicating that the class model and database do not match. Instead, EF will automatically recreate the database to match the new data model class, and our applications will run normally:
Generate initialization data for automatically created databases
In the above, you may have noticed that the meal data we added earlier is lost after the database is rebuilt. This is because the function of automatically rebuilding a database based on model changes is not suitable for actual scenarios. In this case, you want to migrate existing data from one database to another. Instead, it is designed to be suitable for development scenarios, and we need the database structure to be updated automatically quickly-instead of manually or by specifying porting rules.
Note: what we are doing is to provide better data migration services and support version management for product data and database structures. However, we think this is the same as the previous Development ( Development-time ) Functions are different scenarios. This data migration feature will not be released on the CTP of this week.
In fact, EF has provided us with an optional "Seed" function to generate default or test data when creating or recreating a database. I think this function is really practical, because in this way, after I refactor a data model, I can run the application to test immediately-no need to manually input a bunch of test data.
We can implement a "nerddinnersintializer" class as follows to add the "seed" data to the database. I will use it to create two "sample meals" and add them to the database.
Then, we can add the database. initializer () method in global. asax to use this "nerddinnersinitializer" class at startup.
Now, whenever we update the nerddinner model class, the database files will be deleted and rebuilt to match our model class. At the same time, the data of the two default meals will be added to the database for testing.
Easy Reconstruction
The above features make it very easy for us to improve and refactor code during development-without using any tools or scripts to manually synchronize the database structure and code.
Because our model classes, LINQ expressions, and "seed" test data are strongly typed, we can also use Visual Studio's refactoring tool to automatically apply all changes to the Code file.
Step 6: Add verification rules
We have created a simple but good data service application.
However, there is still a problem here, that is, we have not done any data verification to ensure that the data in the database we fill in is correct. Let's fix it.
Use dataannotations for data verification
In ASP. net mvc-based applications, it is usually better to add verification rules to the data model. In this way, maintenance can be performed only in one place, and any controller and view that interacts with it can be forced to follow it. In ASP. net mvc, You can implement data verification through many mechanisms, which can flexibly support any authentication mechanism you want to use.
ASP. net mvc 2 built-in support for using the. NET class librarySYstem. componentmodel. dataannotations validation rule library-you can explicitly use validation rules in model classes by verifying the attribute. You canMy previous blogTo learn more about this feature. We will apply the advantages of this method to the input data verification in our nerddinner application.
Let's look back and add some data verification features to the attributes of the previously defined dinner class. (Note: we also need to add the "using system. componentmodel. dataannotations" namespace .)
[Required] indicates that the data of this attribute must be specified (not empty ). [Stringlength] specifies the maximum string length that can be entered by this attribute. [Regularexpression] The regular expression used to verify input matching is specified for verification (Here we use to verify the email address ).
Each verification feature supports the "errormessage" attribute, which allows us to specify the error message displayed when the verification fails. You can either specify it in a hard-coded way (as above) or get it from a resource file-it is easy to implement localization.
Introduce some CSS and JavaScript files
In the last step, we will return to the create. aspx view template, add the <link> reference site.css file to the project, and add two <SCRIPT> elements to reference two JavaScript files. We also add a line of code before <form> element rendering to call the HTML. enableclientvalidation () method.
These changes will ensure that the verification error messages are displayed in the correct format (to make them more eye-catching), and the validation rules of these data models will be applied at the client and server at the same time.
Run the application
Let's re-run the application and try to register a new dinner party. Let's click the "Create" button before entering data. Now we will find that the verification error message in the model is displayed in the browser:
Since client verification is enabled in ASP. net mvc (a line in the code we wrote above), our error messages will be updated in Real Time:
Note that when the length of the string we input for "title" is greater than 20, the verification error message is changed. This is because the [stringlength] feature we set for dinner. title indicates that the maximum allowed length is 20. When we start to input a string in the "hostedby" text box, the error message starts from "[requred]" (You are required to enter the email address) it becomes "[regularexpression]" (it tells us that no valid email address is entered ).
These verification rules are valid in the browser (through JavaScript) and on the server (even if someone tries to bypass Javascript verification, it can also protect the validity of data input)-no need to make any changes to the Controller class. This ability to specify rules in our model class once so that they can be applied everywhere is extremely powerful-it will allow us to continue to improve our program.
Here you can learn more about the ASP. net mvc 2 model verification functions and how they work.
Download
Click here to download and run the nerddinnerreloaded example we implemented in this blog. You need to install vs 2010 (or free Visual Web Developer 2010 express ).
Important: You must download and install SQL Ce 4 on your computer before running the preceding sample program. You can download the EF code priority class library from here. Both of these downloads will not have a big impact on your machine.
Summary
The "Ef code first" ctp4 released this week provides a good code-centric way to process data. It improves production efficiency and is very powerful. In today's tutorial, I mainly introduced some new features released in ctp4 to improve work efficiency. There are also many other features that we can learn in depth, including its fluent API for customizing persistence ing rules, improved support for testability and other advanced features.
You can download the "Ef code first" published this week from here. If you want to learn more about "Ef code first", you can view the ADO listed below. the blog posted by the net team will learn more about it:
- Blog: EF ctp4 announcement
- Blog: EF ctp4 Improves Production Efficiency
- Blog: EF ctp4 code development strategy
- Dataannotations and Code prior development
- Default specification of the Code priority Library
- Scott hanselman's CTP 4 strategy
I hope this will help you.
Use Entity Framework 4 for Code prior development