[Reprint] dotText source code reading (4)-DTO and data access

Source: Internet
Author: User
From: bytes? These are the implementation content of the Three-layer system. Many senior people have their own opinions on the use of DTO, and there are also a lot of arguments. However, what I want to talk about here is why dottext uses DTO. I understand that the author wants to maintain a layer-3 system through DTO, in order to solve the mutual dependency between layers of coupling, reserve sufficient maintenance space for updates and upgrades between layers. Dottext. framework. data. IDTOProvider defines the DTO interface, which involves the object machine operations: Entry, which is the article published in the blog. The actual body and object declaration are the Entry under the Components directory. cs. Note that this class inherits the IblogIdentifier interface and declares the [Serializable] attribute. Almost all defined object types are similar to this class. The link Categories category in the Links favorites. Note that the system category of the blog is stored together with the category of each blog. The-1 blog is used to distinguish the category defined by the system. Stats statistics Configuration class KeyWords blog keyword Images album Archives Article archive ScheduledEvents scheduling event Logger log object Rate click statistics Security identity authentication MailNotify mail IblogIdentifier interface is specified this class must have a attribution A blogID, this is easy to understand, because both articles and statistical information, personal links, favorites, and folders are private. In addition to object classes, collection classes of corresponding object classes are also implemented. For data binding, many people like to use the entity collection class instead of DataSet. I am also such a person. These object collection classes are also marked with the [Serializable] attribute. You can also use serialization to configure operations on these object classes. dottext defines the IDTOProvider interface to define DTO operations, specifically in Dottext. framework. under the Data directory, this interface needs to be implemented by other specific classes, but it reflects the author's design philosophy: it is not to bind the implementation to the Data layer of the object, which can be used for reference. To further implement your own ideas, dottext also specially clips a data layer abstraction, IDbProvider, which implements data access to various DTC entities, however, the returned IdataReader and DataSet are all defined to encapsulate specific databases. The author of Dottext made a lot of classification comments when writing code. For specific implementation of the Data layer, my version is based on SQL server, and all specific Data operations are performed in SqlDataProvider under the Data Directory. cs, this class implements IdbProvider, but we see almost all of them are stored procedure calls, and there are more than 110 SQL versions of dottext, so read carefully the access details of these data layers, it takes a lot of time. However, after clarifying these clues, we can know how to read and even implement changes.. How does the system implement flexible configuration of data access? For example, the final operation for posting an article falls in admin \ UserControls \ EntryEditor. on ascx (detailed analysis may be added later), the Code is as follows: private void UpdatePost () {if (Page. isValid) {string successMessage = Constants. RES_SUCCESSNEW; try {Entry entry = new Entry (EntryType); entry. title = txbTitle. text ;...... Entry. blogID = Config. currentBlog (Context ). blogID; if (PostID> 0) {successMessage = Constants. RES_SUCCESSEDIT; entry. dateUpdated = DateTime. now; entry. entryID = PostID; entry. link = Dottext. framework. configuration. config. currentBlog (). urlFormats. entryUrl (entry); if (chkIsMoveTo. checked) {entry. postType = entry. postType ^ (PostType) 3);} Entries. update (entry );...... If (PostID> 0) {// LinkCollection lc = new LinkCollection (); ArrayList al = new ArrayList (); int count = cklCategories. items. count; if (chkIsMoveTo. checked) {count = 0 ;}// document category for (int I = 0; I <count; I ++) {if (cklCategories. items [I]. selected) {al. add (Int32.Parse (cklCategories. items [I]. value) ;}/// website category ......} Catch (Exception ex) {this. messages. showError (String. format (Constants. RES_EXCEPTION, Constants. RES_FAILUREEDIT, ex. message);} finally {Results. collapsible = false ;}} the Entry here belongs to the DTO type, which is explained in Components. If it is the first new article, it will execute: Entries. update (entry); execute: public static int Create (Entry entry) {return Create (Entry, null);} static method, and finally call public static int Create (entry Entry, int [] CategoryIDs) {HandlerManager. preCommit (entry, ProcessAction. insert); int result = DTOProvider. instance (). create (entry, CategoryIDs); if (result> 0) {HandlerManager. postCommit (entry, ProcessAction. insert);} return result;} Let's focus on in T result = DTOProvider. instance (). create (entry, CategoryIDs); to execute this statement, make sure that the DTOProvider statement is in the providers Directory: it has a static declaration constructor static DTOProvider () {DTOProviderConfiguration dtoPC = Config. settings. blogProviders. DTOProvider; idto = (IDTOProvider) dtoPC. instance ();} is used to execute the constructor before the method of the class is called statically (this is equivalent to the singleton mode ). In this case, the DTOProvider configuration will be obtained using the configuration system mentioned by the former user. DTOProviderConfiguration has the [XmlRoot ("DTOProvider")] attribute and obtains the DTOProviderConfiguration from the XML snippet obtained in the <BlogProviders> section. Note that the DTOProviderConfiguration here inherits from an abstract class BaseProvider. Config. settings. blogProviders obtains the specific BlogProvider class through deserialization, but we only want to obtain the attributes of DTOProvider, And the configuration in my hands is Dottext. framework. data. dataDTOProvider (note that this class implements the IDTOProvider interface ). The DTOProviderConfiguration type is actually the actual implementation of the abstract class BaseProvider, but with the [XmlRoot ("DTOProvider")] attribute (deserialization is allowed) added, a provider type is obtained. Idto = (IDTOProvider) dtoPC. instance (); dtoPC. instance (); the public object Instance () {return Activator In the BaseProvider (abstract class) is called. createInstance (System. type. getType (this. providerType);} as you can see, this is a dynamic generation method and also uses the reflection principle. The ProviderType Declaration for this class is like this [XmlAttribute ("type")] public string ProviderType {get {return _ type ;}set {_ type = value, this is the Type value read from the configuration file. The specific project value I checked is: Dottext. framework. data. dataDTOProvider, Dottext. in this way, the DataDTOProvider class is instantiated, and DataDTOProvider implements the IDTOProvider interface. Through such a "complex" process, DTOProvider statically constructs an interface that can access the database layer (DTOProvider. instance () Statement) IDTOProvider, while the interface function int Create (Entry entry Entry, int [] CategoryIDs) can be implemented in IDTOProvider ); the following describes the details of the SQL data layer (see implementation class DataDTOProvider): public int Create (Entry entry, int [] CategoryIDs) {if (entry. postType = PostType. pingTrack) {return DbProvider. instance (). insertPingTrackEntry (entry); // DbProvider explained later} FormatEntry (ref entry); if (entry is Ca TegoryEntry) {entry. entryID = DbProvider. instance (). insertCategoryEntry (CategoryEntry) entry);} else {entry. entryID = DbProvider. instance (). insertEntry (entry); if (CategoryIDs! = Null) {DbProvider. instance (). setEntryCategoryList (entry. entryID, CategoryIDs) ;}} if (entry. entryID>-1) // & Config. settings. tracking. useTrackingServices) {entry. link = Dottext. framework. configuration. config. currentBlog (). urlFormats. entryUrl (entry); Config. currentBlog (). lastUpdated = entry. dateCreated;} else {// we need to fail here to stop the PostCommits? Throw new BlogFailedPostException ("Your entry cocould not be added to the datastore");} return entry. EntryID;} Here, the object storage operations for the Entry are implemented. DbProvider is a noteworthy static DbProvider () {DbProviderConfiguration dpc = Config. settings. blogProviders. dbProvider; dp = (IDbProvider) dpc. instance (); dp. connectionString = dpc. connectionString;}: No. It is the same static structure as DTOProvider. The object Dottext. Framework. Data. SqlDataProvider and Dottext. Framework are serialized to a specific database. The following code is used in the DB operation for creating an Entry object: entry. entryID = DbProvider. instance (). insertEntry (entry); SqlDataProvider's InsertEntry operation details are as follows: public int InsertEntry (Entry entry) {SqlParameter [] p = {SqlHelper. makeInParam ("@ Title", SqlDbType. NVarChar, 255, entry. title), SqlHelper. makeInParam ("@ TitleUrl", SqlDbType. NVarChar, 255, DataHelper. checkNull (entry. titleUrl), SqlHelper. makeInParam ("@ Text", SqlDbType. NText, 0, entry. body ), SqlHelper. makeInParam ("@ SourceUrl", SqlDbType. NVarChar, 200, DataHelper. checkNull (entry. sourceUrl), SqlHelper. makeInParam ("@ PostType", SqlDbType. int, 4, entry. postType), SqlHelper. makeInParam ("@ Author", SqlDbType. NVarChar, 50, DataHelper. checkNull (entry. author), SqlHelper. makeInParam ("@ Email", SqlDbType. NVarChar, 50, DataHelper. checkNull (entry. email), SqlHelper. makeInParam ("@ Description", SqlDbType. NVarCha R, 500, DataHelper. checkNull (entry. description), SqlHelper. makeInParam ("@ SourceName", SqlDbType. NVarChar, 200, DataHelper. checkNull (entry. sourceName), SqlHelper. makeInParam ("@ DateAdded", SqlDbType. dateTime, 8, entry. dateCreated), SqlHelper. makeInParam ("@ PostConfig", SqlDbType. int, 4, entry. postConfig), SqlHelper. makeInParam ("@ ParentID", SqlDbType. int, 4, entry. parentID), SqlHelper. makeInParam ("@ EntryName", SQL DbType. NVarChar, 150, DataHelper. checkNull (entry. entryName), BlogIDParam, SqlHelper. makeOutParam ("@ ID", SqlDbType. int, 4)}; NonQueryInt ("blog_InsertEntry", p); return (int) p [14]. value;} indicates no. This is a specific SQL stored procedure call code. In this way, the configuration file is used to specify the DTOProvider and DbProvider instances of BlogProviders. Different Configurations allow you to replace them with different instances. For example, you can replace the DB layer with Mysql. or the specific table operation of Orcal. For more information, see: 1. Static constructor 2. Activator. CreateInstance (System. Type. GetType (this. ProviderType). this method creates an object instance using reflection. In addition, we need to understand that dottext uses a configuration file to dynamically specify the elaborate design of DTO and DB operations (although it is somewhat confusing ). Unfortunately, I found that there seems to be a problem with the version of the blog garden. Many operations, they directly manipulate the database, this may lead to some misunderstandings for me who are not familiar with the source version. The above analysis hopes to eliminate your questions. I stayed up all night :)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.