Preface
In a three-tier structure, the database is the bottom layer and is responsible for database operations, such as adding, deleting, and modifying data. the last figure in the previous article, "Relationship between projects and call graphs", clearly reflects this point. we can also find that the Dal uses a large number of "Factory" forms. what is "Factory ?, What role does "Factory" play in Dal? Let's start with these questions.
Factory Model
The design pattern is a specialized discipline and must be accumulated in practice. There are many popular design patterns, the simplest of which may be the "factory pattern.
The most important feature of the factory model is that the factory class (a) uses the Intelligent Analysis and judgment based on the parameter (p) transmitted by the caller, and selects to return a group with a common parent class (f) subclass of (F1, F2 ...) each subclass performs different operations on the parent class, that is, the factory class creates different subclasses according to the conditions to complete different work. the prototype of the factory model is shown in:
Factory model in petshop 4 System
The factory design model is widely used in petshop 4. All factory classes ending with "Factory" in the project name are abstract, as shown below:
- Dalfactory: The Abstract Factory of the data access layer (determines the database type of data access layer to be created. Available options: sqlserver and Oracle)
- Cachedependencyfactory: The factory class of the cache dependency class. (Create cache dependencies for specific tables)
- Messagingfactory: the abstract factory used to process message queues when an exception occurs (reflection creates a specific exception processing class)
- Profiledalfactory: factory class of profiledal (reflection selects to create profiledal for Oracle and SQL Server)
Taking dalfactory as an example, when a user accesses a database, the user calls the dalfactory class. The dalfactory Class determines whether to instantiate sqlserverdal or oracledal based on the type of the database used by the user, the two Dal classes are inherited from the idal class. After the instance class completes the operation, the idal class is returned. in this way, no matter what type of database is used, the call method and return result are the same. the benefits of doing so are obvious: When the sqlserver database is switched to the Oracle database, you do not need to modify anyProgram.
Data access at the data layer
The factory mode in the petshop4 system is described briefly. In the dalfactory class, there is an important parent class: idal class, which is a set of interfaces for data access. first, let's take a look at the Interface Definition: an interface is just a form of constraint, which includes the definition of members, without defining the specific implementation of members. that is to say, the interface is just an empty shell with a member framework. it must be inherited and implement the member content in the inheritance class. the main purpose of an interface is to provide a general processing service for irrelevant classes. it can implement multi-inheritance.
The idal interface defines the methods required for accessing all databases. but it is implemented in the sqlserverdal and oracledal classes. the advantage of doing so is to facilitate the security of data encapsulation and facilitate future expansion.
Five data access interfaces in the idal class
Interface Name |
File Name Of The. CS File |
Description |
Icategory |
Icategory. CS |
Define access methods for product categories |
Iinventory |
Iinventory. CS |
Define how to access the number of items |
IItem |
IItem. CS |
Define how to access product details |
Iorder |
Iorder. CS |
Define order access methods |
Iproduct |
Iproduct. CS |
Define access methods for products |
Take the iproduct interface as an example:
///
// interface for the product Dal
///
Public interface iproduct {
///
// method to search products by category name
///
// name of the category to search by
// interface to model collection generic of search results
ilist getproductsbycategory (string category );
//
// method to search products by a set of keyword
///
/// an array of keywords to search by
// interface to model collection generic of search results
ilist getproductsbysearch (string [] keywords );
/// <Summary>
/// Query for a product
/// </Summary>
/// <Param name = "productid"> product ID </param>
/// <Returns> interface to model productinfo for requested product </returns>
Productinfo getproduct (string productid );
}
Note:
- When you view the definitions of these interfaces, the namespace format is retained in the file. In fact, the displayed namespace has been canceled in ASP. net3.5.
- Interface-definedCodeI also used generics. I still need to enhance the extensive knowledge.
Sqlserverdal implementation
The product class in sqlserverdal defines SQL statements and their parameters as multiple constants. This makes it easier to maintain and analyze these constants carefully and finds that their combinations are flexible, you can easily perform queries under multiple conditions, such as by category, by ID, or by name and category ID.
// static constants
private const string SQL _select_products_by_category = "select product. productid, product. name, product. descn, product. image, product. categoryid from product where product. categoryid = @ category ";
private const string SQL _select_products_by_search1 =" select productid, name, descn, product. image, product. categoryid from product where (";
private const string SQL _select_products_by_search2 =" lower (name) like '%' + {0} + '%' or lower (categoryid) like '%' + {0} + '%' ";
private const string SQL _select_products_by_search3 =") or (";
private const string SQL _select_products_by_search4 = ")) ";
private const string SQL _select_product =" select product. productid, product. name, product. descn, product. image, product. categoryid from product where product. productid = @ productid ";
private const string parm_category =" @ category ";
private const string parm_keyword =" @ keyword ";
private const string parm_productid = "@ productid";
The product class implements functions in several ways:
- Public ilist <productinfo> getproductsbycategory (string category) // query for products by category
- Public ilist <productinfo> getproductsbysearch (string [] keywords) // query for products by keywords. The results will include any product where the keyword appears in the category name or product name
- Public productinfo getproduct (string productid) // query for a product
In the process of implementing the method, a database access assistant of MS is used: sqlhelper class (or oraclehelper class). The introduction of sqlhelper class is described in my previous blog posts, if you are interested, find out.
The implementation of oracledal is similar to that of sqlserverdal.
Dalfactory implementation
In dalfactory, an important aspect is to judge the database type used. This task is completed by the daraaccess class. An important static variable path in this class is as follows:
// Look up the Dal implementation we shoshould be using
Private Static readonly string Path = configurationmanager. deleettings ["webdal"];
Configurationmanager is a class used to obtain node information in the web. congig file. The path is from the webdal project of the appsettings node. Open the Web. config file and you can find it:
<Add key = "webdal" value = "petshop. sqlserverdal"/>
This webdal project specifies the type of the database currently in use. modify it to modify the Dal class to be instantiated below.
Dalfactory judges the class to be instantiated. How does it implement instantiation?
In the daraaccess class, there are five classes with similar names as idal classes. They are the methods used to instantiate interfaces in idal. The createcategory method is used as an example:
Public static petshop. idal. icategory createcategory (){
String classname = path + ". Category ";
Return (petshop. idal. icategory) Assembly. Load (PATH). createinstance (classname );
}
The returned values above are worth studying:
- First, a forced type conversion is adopted to convert the returned results to the icagegory type.
- Second, load is used to load the specified database processing class.
- Finally, use the createinstance method to find the specified type from the program set, and then create its instance.