From Zhang Ziyang http://www.cnblogs.com/JimmyZhang/archive/2009/05/18/1459330.html
The purpose of this tutorial is to explain an ASP. net mvc application.ProgramCreate a model class. In this tutorial, you will learn how to use Microsoft LINQ to SQL to create model classes and perform database access.
In this tutorial, we created a basic movie database application. We try our best to create a Movie Database Application in the fastest and simplest way. We directly perform all data access from the Controller action.
Next, you will learn how to use the repository mode. Using the repository mode requires more work. However, the advantage of using this mode is that it allows you to create applications that can adapt to changes and test simple applications.
1. What is a model class?
The MVC model contains all the application logic not included in the MVC view or the MVC controller. Specifically, an MVC model contains all application business and data access logic.
You can use different technologies to implement your data access logic. For example, you can use the Microsoft Entity Framework, nhib.pdf, subsonic, or ADO. Net class to build your data handler class.
In this tutorial, I use LINQ to SQL to query and update databases. LINQ to SQL provides you with a very simple way to interact with the Microsoft SQL Server database. However, it is very important to understand the ASP. net mvc framework that is not limited to LINQ to SQL. ASP. net mvc is compatible with any data access technology.
2. Create a Movie Database
In this tutorial, we created a simple Movie Database Application to demonstrate how to build a model class. The first step is to create a new database. Right-click the app_data folder in the solution browser window, and select "add" and "new item" from the menu )". Select the SQL Server database template, name it moviesdb. MDF, and click "add" (1 ).
Figure 1: Add a new SQL Server database
After creating the new database, you can open the database by double-clicking the moviesdb. MDF file in the app_data folder. Double-click the moviesdb. MDF file to open the "Server Explorer" window (2 ).
When Visual Web Developer is used, "server resource manager" is called "Database Explorer )".
Figure 2: Use the "server resource manager" Window
We need to add a table in the database, which represents a movie. Right-click the tables folder and select "Add new table" from the menu )". Select this menu item to open "Table Designer" (3 ).
Figure 3: Table Designer
We need to add the following columns to our database table:
Column name |
Data Type |
Allow null |
ID |
Int |
False |
Title |
Nvarchar (200) |
False |
Director |
Nvarchar (50) |
False |
You need to do two special tasks for the ID column. First, you need to select a column in the Table Designer and click the key icon to identify the ID column as the primary key column. When you insert or update a database, you must specify the primary key columns for LINQ to SQL.
Next, you need to mark the ID column as the identity column (3) by assigning the isidentity attribute to the yes value ). Each time you add a new row of data to a table, the identity column automatically assigns a new number.
3. Create a LINQ to SQL class
Our MVC model class will contain the LINQ to SQL class, which represents the tblmovie database table. The easiest way to create a LINQ to SQL statement is to right-click the models folder, select "add", "new item", and select a LINQ to SQL template, name the class movie. dbml, and click "add" (4 ).
Figure 4: Create a LINQ to SQL class
After creating the movie LINQ to SQL class, the "Object Relational designer" will appear immediately )". You can drag a database table from the "Server Explorer" window to the "Object link designer" to create a LINQ to SQL class that represents a specific database table. We need to add the tblmovie database table to "Object link designer" (5 ).
Figure 5: Use the object link designer"
By default, the class created by the object link designer is exactly the same as the name of the database table you dragged to the designer. However, we don't want to care about our class called tblmovie. Therefore, click the class name in the designer and change the class name to movie.
Finally, remember to click "save" to save the LINQ to SQL class. Otherwise, the LINQ to SQL class will not be generated by the object link designer.
4. Use LINQ to SQL in controller actions
Now that we have the LINQ to SQL class, we can use these classes to retrieve data from the database. In this section, you will learn how to use the LINQ to SQL class directly in the Controller action. We will display the movie list from the tblmovies database table in an MVC view.
First, we need to change the homecontroller class. This class can be found in the controllers folder in your application. Modify this class to make it look likeCodeAs shown in Listing 1.
Code List 1-controllershomecontroller. CS
UsingSystem. LINQ;
UsingSystem. Web. MVC;
UsingMvcapplication1.models;
NamespaceMvcapplication1.controllers {
[Handleerror]
Public Class Homecontroller:Controller{
PublicActionresult index (){
VaRDatacontext =New Moviedatacontext();
VaRMovies = from mInDatacontext. Movies
Select m;
ReturnView (movies );
}
}
}
The index () Action in code list 1 uses the LINQ to SQL datacontext class (moviedatacontext) to represent the moviesdb database. The moviedatacontext class is generated by Visual Studio "Object link designer.
The index () Action executes a LINQ query on datacontext to retrieve all movies from the tblmovies database table. The movie list is assigned a local variable called movies. Finally, the movie list is passed to the view through View data.
To display the movie list, we need to modify the index view. You can find the index view in the viewshome folder. Update the index view to make it the same as the view in code list 2.
Code List 2-viewshomeindex. aspx
<% @ Page Language = "C #" masterpagefile = "~ /Views/shared/site. master "autoeventwireup =" true "codebehind =" index. aspx. CS "inherits =" mvcapplication1.views. home. index "%> <% @ import namespace =" mvcapplication1.models "%> <asp: Content ID =" indexcontent "contentplaceholderid =" maincontent "runat =" server ">
<Ul>
<% Foreach (movie m in (ienumerable) viewdata. Model)
{%>
<Li> <% = M. Title %> </LI>
<% }%>
</Ul>
</ASP: content>
Note that the modified index view contains a <% @ import namespace %> indicator at the top of the view. This indicator introduces the mvcapplication1.models namespace. To process the model class, we need this namespace, especially the movie class in the view.
The view in code list 2 contains a foreach loop that traverses all items represented by the viewdata. model attribute. Displays the title attribute value of each movie.
Note that the viewdata. model attribute is forcibly converted to an ienumerable. This is required to traverse the content of viewdata. model. Another option is to create a strongly typed view. When you create a strongly typed view, you forcibly convert the viewdata. model attribute to a specific type in the Code class behind the view.
If you run the application after modifying the homecontroller class and index view, you will get a blank page. You get a blank page because there is no movie record in the tblmovies database table.
To add records to the tblmovies database table, right-click the tblmovies database table in the "server resource manager" window (called "Database Resource Manager" in Visual Web Developer, select Show table data from the menu )". You can use the displayed mesh to insert movies records (6 ).
Figure 6: Insert a movie
After you add some database records to the tblmovies table and run the application, you will see the page shown in figure 7. All Movie Database records are displayed in the project symbol list.
Figure 7: display a movie in the index View
5. Use repository Mode
In the previous section, we directly used LINQ to SQL in a controller action. We directly use the moviedatacontext class from the index () controller action. This is no problem for a simple application. However, when you need to build more complex applications, directly processing LINQ to SQL in the Controller class will cause some problems.
Using LINQ to SQL in the Controller class makes it difficult to switch Data Access Technologies in the future. For example, you may want to switch Microsoft LINQ to SQL to use Microsoft Entity Framework as your data access technology. In this case, you need to re-write the Controller that accesses the database in the application.
Using LINQ to SQL in the Controller class makes it more difficult to create unit tests for applications. Generally, you do not need to interact with the database when executing a unit test. You want to use unit tests to test your application logic, not your database server.
To Build MVC applications that are more adaptable to future changes and easier to test, you should consider using the repository mode. When you use the repository mode, you will create an independent repository class that contains all the data access logic.
When you create a repository class, you create an interface that represents all the methods used by the repository class. In your controller, you write code for interfaces instead of for repository. In this way, you can use different data access technologies to implement repository.
The interface in code listing 3 is named imovierepository and contains a method called listall ().
Code List 3-modelsimovierepository. CS
UsingSystem. Collections. Generic;
NamespaceMvcapplication1.models {
Public Interface Imovierepository{
Ilist <movie> listall ();
}
}
The repository class in code list 4 implements the imovierepository interface. Note that it contains a method called listall (), which corresponds to the method required by the imovierepository interface.
Code list 4-modelsmovierepository. CS
UsingSystem. Collections. Generic;
UsingSystem. LINQ;
NamespaceMvcapplication1.models {
Public Class Movierepository:Imovierepository{
Private Moviedatacontext_ Datacontext;
PublicMovierepository (){
_ Datacontext =New Moviedatacontext();
}
# Region imovierepository members
PublicIlist <movie> listall (){
VaRMovies = from mIn_ Datacontext. Movies
Select m;
ReturnMovies. tolist ();
}
# Endregion
}
}
Finally, the moviescontroller class in code list 5 uses the repository mode. It no longer directly uses the LINQ to SQL class.
Code List 5-controllersmoviescontroller. CS
UsingSystem. Web. MVC;
UsingMvcapplication1.models;
NamespaceMvcapplication1.controllers {
Public Class Moviescontroller:Controller{
Private Imovierepository_ Repository;
PublicMoviescontroller ():This(NewMovierepository ()){}
PublicMoviescontroller (imovierepository repository ){
_ Repository = repository;
}
PublicActionresult index (){
ReturnView (_ repository. listall ());
}
}
}
Note that the moviescontroller class in code listing 5 has two constructors. The first constructor, a non-parameter constructor, is called when your application is running. This constructor creates an instance of the movierepository class and passes it to the second constructor.
The second constructor has only one parameter: One imovierepository parameter. This constructor simply assigns the parameter value to a class-level field called _ repository.
The moviescontroller class utilizes the dependency injection mode in the software design mode. Specifically, it uses constructor dependency injection ). You can read the following article by Martin Fowler.ArticleTo read more information about this mode:
Http://martinfowler.com/articles/injection.html
Note that all the code in the moviescontroller class (except the first constructor) interacts with the imovierepository interface, rather than the actual movierepository class. The Code interacts with an abstract interface, rather than the specific implementation of the interface.
If you want to modify the data access logic used by the application, you can simply use a class to implement the imovierepository interface, which uses different database access technologies. For example, you can create an entityframeworkmovierepository class or a subsonicmovierepository class. Because the Controller class is designed for interfaces, you can pass a new implementation of imovierepository to the Controller class, and this class will continue to work.
In addition, if you want to test the moviescontroller class, you can pass a pseudo movie respository class to homecontroller. You can implement imovierepository by using a class that does not actually access the database but contains all the methods required by the imovierepository interface. In this way, you can perform unit tests on the moviescontroller class without actually accessing a real database.
6. Summary
The purpose of this tutorial is to demonstrate how to create an MVC model class using Microsoft LINQ to SQL. We have explained two strategies for displaying database data in ASP. net mvc applications. First, we directly create and use the LINQ to SQL class in the Controller action. Using the LINQ to SQL class in the Controller enables you to quickly and easily display database data in MVC applications.
Next, we explored a little more difficult, but it is definitely a better way to display database data. We use the repository mode and place all the database logic in an independent repository class. In our controller, all the code we write is for an interface, not an entity class. The repository mode allows us to easily change data access technologies in the future and allows us to easily test our controller classes.