Implement a non-reflective green ORM framework using abstraction and Polymorphism

Source: Internet
Author: User

Recently, I have been busy with the basic library construction of new companies, and have accumulated some practical experience in system architecture, development framework, and quick development platform design and implementation.

It is feasible for medium and small software development companies to evaluate the technical content of software projects based on technical reserves. However, it is unreliable to measure the technical content of software by human head alone. Therefore, when we choose to jump to the nest, we should choose a large company or a technical company based on our career plans. (I recently learned a little bit about nest jump experience to share with you)

As the technical department of my current organization has just been established and some basic development frameworks are required, Orm certainly cannot run. In the subsequent articles, I will write down some practical tests in the construction of the basic framework, which may include encapsulation of the UI Layer and encapsulation of basic controls. I am not talking nonsense.

This article focuses on the non-reflective ORM framework. Why is there such an idea? In fact, some friends in the group recently asked some questions. They frequently use reflection to write functions when building their own ORM frameworks. From the perspective of communication with them, they seem to like to use reflection to write functions, but they have not carefully studied where the role of the orm framework lies in the system architecture, reflection is a bit powerless when the performance requirements are very strict.

Of course, there is no doubt about the advantages of reflection. Some technologies are slightly better or big players usually use dynamic compilation technology to smooth out the most important performance bottleneck of the system. I always think that we can use high-level abstraction and conventions to solve the problem of using reflection in this Orm. Next we will analyze why the ORM framework usually needs reflection and what the purpose of reflection is. [Wang qingpei has all rights reserved. For more information, please sign it.]

What is the purpose of reflection in Orm?

Of course, we are talking about the most common and necessary problems here.

The types and forms of ORM frameworks vary, and different companies have different ORM implementations. In fact, the purpose is to have a set of development frameworks for your own company. This is not a technical decision, but a requirement of the company's senior leadership. (We do not have the right to speak. To save our job, we have to obey the command)

However, most of the design ideas and Implementation ideas of the ORM framework are inseparable from those "thinking implementation constraints ". Why should I say "thinking implements constraints"? This is also one of the common problems of our programmers. They all like to use complicated technologies. No matter how comfortable it is. This is a good thing, so that you can understand the technology. Without this curiosity, it is hard for us to reach the expert position.

Purpose: To express the ing between objects and tables

Orm is a ing between entities and tables. It is gradually developed into a complex technical implementation model.

In the traditional layered architecture, a feature is used in the definition of an object to mark the table name represented by the object. For example:

[Serializable ()]

[Hz. Table (tablename = "member")]

Public class member {}

The attribute tablename in the feature Hz. Table stores the static table name. In the Orm, you can obtain the object type and then reflect the property metadata of this type. Read the attribute values of related members as a required condition for splicing SQL statements.

Objective 2: To express the correspondence between attributes and fields and some primary and Foreign keys

In Orm, ing object attributes into fields of tables in the database can be expressed in two ways.

First, the field name represented by this attribute is represented by the attribute feature;

[Hz. Column (primarykey = true, columnname = "memberid")]

Public String membercode {Get; set ;}

Type 2: The field name is directly indicated by the attribute name;

Public String memberid {Get; set ;}

Objective 3: To obtain values in Object Attributes

When inserting or updating an object, you need to obtain the attribute value in the object. In this case, you can only obtain the attribute value through reflection, and then splice the insert or update statement.

Objective 4: To set object attribute values

You can instantiate a generic object and then use the setvalue method to set the attribute value of the reflection object.

Summary: these are the most common features and may include other complex functions. I will not cover them here. All of the above information is obtained through reflection, and reflection is required for addition, deletion, modification, and query. Especially for data query, the query performance of a large amount of data is very scary.

Design non-characteristic ORM entities through abstraction and Polymorphism

Most ORM frameworks require the support of code generators. Not all codes need to be manually typed by programmers. You can use some template engine-class code generators, edit your template and generate most of the entity code. Including entityframework and linqtosql in. Net, which are also integrated with IDE code generators.

Therefore, the considerations for enterprise code generators will be involved here, so we will not talk about it here. We will discuss it in a later article.

Let's first discuss how to design the entity structure so that it can contain the necessary information required by our Orm. In fact, our thinking is slightly changed to using abstraction to solve the problem. Raise the abstract level and regard the entity as two layers. The top-level abstract class is used by Orm, And the subclass is used by callers.

Figure:

Our requirement is that there cannot be a reflected code in the Orm. Therefore, we agree on the basicentityobject abstract class. By defining the top-level abstract base class, we can include some attribute information required by the subclass.

Let's take a look at what the abstract class contains.

Using system; using system. collections. generic; using system. text; using system. collections; namespace glory. net. orm {public abstract class baseentityobject: dictionarybase {// <summary> // table name in the database corresponding to the object /// </Summary> private string _ tablename = string. empty; // <summary> // protected dictionary: the attributes and attribute types of the primary keys in the database table corresponding to the object class. /// </Summary> protected dictionary <string, string >_primarydictionary = new dictionary <string, string> (); /// <summary> /// used to set the table name in the database corresponding to the current subclass for the object subclass. /// </Summary> protected string tablename {get {return _ tablename ;} set {_ tablename = value ;}} /// <summary> // obtain the table name in the corresponding orm of the current instance using the client code /// </Summary> Public String gettablename {get {return _ tablename ;}} /// <summary> /// used to set the attribute value of the current instance for the object subclass // </Summary> /// <Param name = "key"> </param>/ // <returns> </returns> protected object this [String key] {get {return this. dictionary [Key];} set {This. dictionary [Key] = value ;}} /// <summary> /// set the attribute value of the Instance /// </Summary> /// <Param name = "key"> attribute name </param> /// <Param name = "value"> attribute value </param> Public void setentityvlues (string key, object value) {If (this. dictionary. contains (key) {This. dictionary [Key] = value ;}} /// <summary> /// obtain the attribute key value Team of the Instance // </Summary> /// <returns> </returns> Public idictionary getentityvalue {get {return (idictionary) this. dictionary; }}/// <summary> // obtain the instance's primary key information // </Summary> Public idictionary getentityprimary {get {return (idictionary) _ primarydictionary ;}} protected abstract void addprimarytodictionary ();}}

In fact, the code is very simple, just to save the property value of the subclass to the base class, so that the subclass is just an empty shell.

Public class tb_car: vluesinittb_car {/// <summary> // unique primary key // </Summary> Public String CID {get {return this ["CID"] as string ;} set {This ["CID"] = value ;}} /// <summary> /// license plate number /// </Summary> Public String carbanrdcode {get {return this ["carbanrdcode"] as string ;} set {This ["carbanrdcode"] = value ;}/// <summary >///// </Summary> Public String carcode {get {return this ["carco De "] as string;} set {This [" carcode "] = value ;}} /// <summary >///// </Summary> Public String drivername {get {return this ["drivername"] as string ;} set {This ["drivername"] = value ;}} /// <summary >/// contact number /// </Summary> Public String mobile {get {return this ["mobile"] as string ;} set {This ["mobile"] = value ;}/// <summary> /// model /// </Summary> Public String cartype {get {re Turn this ["cartype"] as string;} set {This ["cartype"] = value ;}} /// <summary> /// purchase date /// </Summary> Public datetime? Buydatetime {get {return this ["buydatetime"] As datetime ?;} Set {This ["buydatetime"] = value ;}/// <summary> // center ID. Foreign key // </Summary> Public String attachcenter {get {return this ["attachcenter"] as string ;}set {This ["attachcenter"] = value ;}} /// <summary> /// Region ID. Foreign key // </Summary> Public String attachsection {get {return this ["attachsection"] as string ;}set {This ["attachsection"] = value ;}} /// <summary> /// ID of the website to which the object belongs. Foreign key // </Summary> Public String attachstop {get {return this ["attachstop"] as string ;}set {This ["attachstop"] = value ;}}}

So why is the middle class used to isolate initialization from the base class;

[Serializable ()] public class vluesinittb_car: baseentityobject {public vluesinittb_car () {This. tablename = "tb_car"; // <summary> /// unique primary key /// </Summary> This. dictionary. add ("CID", null); // <summary> // license plate number /// </Summary> This. dictionary. add ("carbanrdcode", null); // <summary> /// </Summary> This. dictionary. add ("carcode", null); // <summary> /// </Summary> This. dictionary. add ("dri Vername ", null); // <summary> // contact number // </Summary> This. dictionary. add ("mobile", null); // <summary> // model /// </Summary> This. dictionary. add ("cartype", null); // <summary> // date of purchase /// </Summary> This. dictionary. add ("buydatetime", null); // <summary> // the ID of the center to which the object belongs. Foreign key /// </Summary> This. dictionary. Add ("attachcenter", null); /// <summary> /// the ID of the region to which it belongs. Foreign key /// </Summary> This. dictionary. Add ("attachsection", null); // <summary> /// site ID. Foreign key /// </Summary> This. dictionary. add ("attachstop", null); addprimarytodictionary () ;}/// <summary> // The entity class overrides the object base class to add the primary key information method, the first letter of the primary key data type must be capital. // </Summary> protected override void addprimarytodictionary () {_ primarydictionary. add ("CID", "string ");}}

This level of abstraction can be used to avoid performance problems caused by features. In Orm, all our generic methods constrain the entity to the baseentityobject type, and all the information, including the primary key, field, and data type, can be obtained through polymorphism.

Orm instantiates an object instance and caches it for future use. Without the need to frequently instantiate intermediate objects.

In fact, most of the code can be generated through the code generator. We are also developing a code generator for the company that conforms to our own products, this includes highly abstract business code and code generation after business modeling.

Of course, this article is just a simple explanation of the core content. I hope it will be helpful to everyone. [Wang qingpei has all rights reserved. For more information, please sign it.]

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.