Linqtodb Source Code Analysis--Generate and Execute SQL statements

Source: Internet
Author: User

The ability to generate SQL statements can be considered the last step of the LINQTODB framework. From the previous chapter we know that after the expression tree has been processed, the related generated SQL information is saved in an instance called the SelectQuery class. With this example, we can generate the corresponding SQL statement. To understand the functionality of this step, you must start with three aspects. One, the mechanism of LINQ to SQL principle. Second, how to generate SQL statements. Third, set the mapping result.

Generating a mapping expression

The mechanism of LINQ to SQL has been discussed in the previous chapters. Here the author proposes that the main goal is to specify when to trigger. The following code does not look at the previous get Query<t> class real column, but instead looks at the subsequent Getienumerable method call.

Expressionquery<t> class:

Ienumerable<t> Execute (idatacontextinfo datacontextinfo, expression expression) {    return  true). getienumerable (null, datacontextinfo, expression, Parameters);}

I remember the author of the previous chapters in the end will call the two methods are Query<t> class Getienumerable method and GetElement method. Both of these methods are func types. As follows

 Public Object Object> getelement;  Public Object [], ienumerable<t>> getienumerable;

Obviously it is obvious that you must know which method to assign to the Getienumerable method when calling it. All right, let's just pause for a moment. Let's take a look at the previous chapter of the Build<t> () method There are three important methods of a--buildquery () method.

1 InternalQuery<t> build<t>()2 {3      varsequence = Buildsequence (NewBuildinfo ((Ibuildcontext)NULL, Expression,Newselectquery ()));4 5       if(_reorder)6            Lock(_sync)7            {8_reorder =false;9_sequencebuilders = _sequencebuilders.orderbydescending (_ = _. Buildcounter). ToList ();Ten            } One  A _query. Init (sequence, currentsqlparameters); -  -        varparam = Expression.parameter (typeof(query<t>),"Info"); the  -        sequence. Buildquery ((query<t>) _query, param); -  -        return(query<t>) _query; +}

The fact that before calling the Getienumerable method, the above Buildquery () method has already assigned a new method to the getienumerable. For the Buildquery () method just click inside to see, you will find that he does not belong to the Xxxxbuilder class. Instead, it belongs to the Ibuildcontext interface instance that corresponds to the Xxxxbuilder class. For example, below

Tablecontext class:

 Public void Buildquery<t> (query<t> Query, parameterexpression queryparameter) {    var expr = Buildquery (typeofthisnull);     var mapper = builder.buildmapper<t>(expr);    Query. Setquery (mapper);}

It seems that there is no code assigned to getienumerable. Don't be nervous. Let's take a look at what this code does. Let's say we've generated the SQL statement and we've executed the database. So what does it look like to have the results of the database mapped into object classes? It seems that everyone must understand the author's meaning. Nothing wrong. This is the mapping that sets the return result. Also, the sub-author constructs a method with an expression to set the return object result. In particular, the reader can take a break to see it himself. The mapper is the last generated mapping expression tree. We can see that he passed the Setquery () method as a parameter.

Query<t> class:

Internal void Object [], t>> expression) {    var query = getquery ();     var New MapInfo {expression = expression};    Clearparameters ();     0 ), CTX, DB, expr, PS, mapInfo);}

OK, see this section of code. We can see him build a MapInfo class. I remember the previous chapters of the picture has appeared. The result of the final database is the transformation of the MapInfo class into related object results. And this way we can see that the getienumerable is being re-assigned. Why is it that it was re-assigned. Because the getienumerable is already assigned in the constructor of the Query<t> class. Readers can take a look at them.

At this point we can understand that calling the Getienumerable method is, in fact, a map method that calls the assignment in the code above. So it's obvious to see how the map method does is to understand how to invoke the author build method. That is the method of building the expression mentioned above.

Generating SQL statements

Finally, the database must be executed, this step can not be separated from the Getienumerable method mentioned above. We also know that the Getienumerable method is actually calling the map method. In this process, a class called Preparedquery is used. This class is the pre-query class used to execute the database. The generated SQL statements are stored inside.

Query<t> class:

1TE runquery<te>(2 Querycontext CTX,3 Idatacontextinfo Datacontextinfo,4 Expression expr,5             Object[] Parameters,6Func<querycontext, Idatacontext, IDataReader, Expression,Object[], te>mapper)7 {8             varDataContext =Datacontextinfo.datacontext;9 Ten             object query = null; One  A             Try -             { -                 query = SetCommand (dataContext, expr, parameters, 0, true); the  -                 using(varDr =datacontext.executereader (query)) -                      while(Dr. Read ()) -                         returnMapper (CTX, DataContext, Dr, expr, parameters); +  -                 returnArray<te>. Empty.first (); +             } A             finally at             { -                 if(Query! =NULL) - datacontext.releasequery (query); -  -                 if(Datacontextinfo.disposecontext) - datacontext.dispose (); in             } -}

The above code is the entry point for executing the database. The author uses red to mark out the relevant code for what I did before executing the database--generating the SQL statement. However, we will find that query is not a string but a Preparedquery class instance. So let's take a look at where the preparedquery is generated, and we can understand that generating SQL statements is inseparable from a class called Basicsqlbuilder.

DataConnection class:

1 Internalpreparedquery GetCommand (iquerycontext query)2 {3      if(Query. Context! =NULL)4      {5           return NewPreparedquery6           {7Commands = (string[]) query. Context,8SqlParameters =query. Selectquery.parameters,9SelectQuery =query. SelectQuery,TenQueryhints =query. Queryhints, One           }; A      } -  -      varsql =query. Selectquery.processparameters (); the      varNewsql =processquery (SQL); -  -      if(!Object. ReferenceEquals (SQL, newsql)) -      { +sql =Newsql; -Sql. Isparameterdependent =true; +      } A  at      var sqlprovider = Dataprovider.createsqlbuilder (); -  -      var cc = sqlprovider.commandcount (sql); -      var sb = new StringBuilder (); -  -      varcommands =New string[CC]; in  -       for(vari =0; i < CC; i++) to      { +Sb. Length =0; -  the sqlprovider.buildsql (i, SQL, SB); *           commands[i] = sb. ToString (); $      }Panax Notoginseng  -      if(!query. Selectquery.isparameterdependent) theQuery. Context =commands; +  A       return NewPreparedquery the       { +Commands =commands, -SqlParameters =SQL. Parameters, $SelectQuery =SQL, $SQLProvider =SQLProvider, -Queryhints =query. Queryhints, -        }; the}

The red part above is the code Question section that generates the SQL statement. For the Basicsqlbuilder class author simple to do some introduction. To do a preliminary understanding. Want a deeper understanding. It's best to check the code yourself. The Basicsqlbuilder class is divided according to DML. So we can see the following methods

1.BuildSelectQuery method: Constructs a query statement. 2.BuildDeleteQuery method: Constructs a DELETE statement. 3.BuildUpdateQuery method: Constructs an UPDATE statement. 4.BuildInsertQuery method: Constructs an INSERT statement.
Wait a minute

At the same time, according to the results of SQL statements are divided into the following methods.

1.BuildSelectClause: The keyword Select section of the statement. 2.BuildFromClause: The keyword from section of the statement. 3.BuildWhereClause: The keyword where section of the statement. 4.BuildGroupByClause: The keyword groupby section of the statement. Wait a minute

Basicsqlbuilder class In fact, I think it is relatively simple. And the author's goal is to guide a way to view the source of ideas. Want to learn from the source of things or to rely on their own to analyze the line.

concluding sentence

This series of articles can only guide the author here. The author of this series of positioning is to help people who want to understand the LINQTODB framework to do a guide and analytical thinking work. As said above to learn from the source of things or to rely on their own to analyze the line.

Linqtodb Source Code Analysis--Generate and Execute SQL statements

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.