. NET Surface Question series [+]-LINQ to Object

Source: Internet
Author: User
Tags management studio sql management studio

. NET face Question series catalogue famous aphorism

"all Features of C # 3.0 are made better for linq"-learning hard

LINQ is an abbreviation for language Integrated query (language-integrated queries), with the same pronunciation and word link. Don't read it as "lin-q".

LINQ to object converts a query statement to a Delegate. LINQ to entity converts a query statement to an expression tree before converting it to Sql.

The benefit of Linq: strong typing, which is more object-oriented than SQL statements, and provides a unified approach to all Databases.

Some of the problems with LINQ are that you should always be concerned with converting SQL to maintain performance, and some operations cannot be converted to SQL statements, and it is difficult to override stored Procedures.

In the interview, most interviewers will not let you write LINQ query, at least as far as I can not write the LINQ join is not so-called, anyway, check the book must be Written. But the interviewer will be interested in whether you understand the principles of LINQ. As a matter of fact, LINQ is equal to the presence of a delegate, and the following features can be considered as syntactic sugars. If you can use the original delegate to implement a where,select-like feature in LINQ without linq, you should understand LINQ to Object Well.

What is enumerable?

Enumerable is a static type that contains many methods, most of which are extension methods (it also has its own method, such as range), and returns IEnumerable (because IEnumerable is lazy-loaded, Values are only available for each visit), and most of the extensions are ienumerable<t>.

Enumerable is a static type and cannot create an instance of the enumerable Type.

Enumerable is the basis for LINQ to Object. Because LINQ to object deals Most of the time with ienumerable<t> and its derived classes, it extends the enumerable class of ienumerable<t>, giving Ienumerable<t > Powerful Query Capabilities.

Sequence (Sequence)

A sequence is like a carousel of data items, and you can only get one at a time until you don't want to get or sequence no Data. The sequence can be infinite (for example, you can write an infinite sequence of random numbers), and when you read data from a sequence, you usually don't know how many data items are waiting to be read.

A LINQ query is the acquisition of a sequence, which is then usually converted to another sequence in intermediate processes, or joined with an additional sequence.

Deferred execution (lazy Loading)

Most LINQ statement is when the first element of the final result is accessed (that is, the foreach call MoveNext in METHOD) to actually start the operation, a feature called deferred Execution. In general, an operation that returns another sequence (typically ienumerable<t> or iqueryable<t>), using deferred execution instead of a single value operation, is executed immediately.

For example, the following example: in fact, when these two lines of code run out, ToUpper is not running at All.

Or the more extreme examples below, Although there are many statements, the statement does not take any time until you intend to traverse the results:

So if we write like this, will there be anything to print out?

The answer is No. The key to the problem is that,ienumerable<t> is deferred, and when no execution is triggered, no operations are Performed. Select method does not trigger LINQ of the Implementation. some of the triggering methods are:

    • foreach Loop
    • Tolist,toarray,todictionary methods, etc.

For example, the following code:

Its output is:

Note that all names are printed, and all uppercase names are printed with a length greater than 3. Why do you print alternately? This is because when the Foreach enumeration is started, the members of the uppercase are not sure, we run select first, Print the original, and then filter if the length is greater than 3, so the result is alternating between uppercase and Original.

Enforcing LINQ statements with ToList

The difference between the following code and the above is that we have added a tolist method. What does thinking output?

The ToList method enforces all LINQ Statements. So the uppercase is determined before the foreach Loop. It will consist of only three members: Lily,joel and Annie (both uppercase). It will print 5 first names, then print the three members in the uppercase, and the result is:

LINQPad

The LINQPad tool is a good LINQ query Visualizer. It was written by threading in C # and the author Albahari of C # in a nutshell, completely free of charge. It's a http://www.linqpad.net/.

After entering the interface, LINQPad can connect to the existing database (but only Microsoft's SQL Server system, if you want to connect to other types of databases you need to install plug-ins). Instead of SQL Management studio, It is a powerful tool for code farmers using SQL Management Studio as a database management software that can be used for debugging and performance optimizations (by improving the compiled SQL scale).

You can use the Northwind Presentation database for LINQ Learning. The Northwind demo database is https://www.microsoft.com/en-us/download/details.aspx?id=23654. After connecting to the database, LINQPad supports querying using SQL or C # statements (point tags or query expressions). You can also see the different expressions of a query expression by clicking on various formats in the orange circle:

    • Lambda: lambda expression version of a query expression
    • Sql: SQL converted by the compiler, usually this is the part we care about most
    • Il:il language

Query operations

Suppose we have a class ProductInfo and an array in the main thread that contains members of several productinfo. Before we write the query, we pass in the object product, which is of type productinfo[].

Basic selection syntax

Get all the information for all products in product (note that P is an alias that can be arbitrarily named):

From P in products

Select P

Sql:select * FROM Products

Get product name for all Products:

From P in products

Select P.name

Sql:select name from Products

WHERE clause

Get all the information for all products in product, but must numberofstock attribute greater than 25:

From P in products

where P. numberofstock > 25

Select P

Sql:select * FROM Products where Numberofstock > 25

Any valid C # operator can be used in the Where clause, &&,| | And so on, this is equivalent to Sql's and and Or.

Note that the last select P is actually meaningless and can be removed. If the SELECT clause does nothing but returns the same sequence as the given sequence, the compiler deletes it. The compiler will translate this LINQ statement into Product.where (p = P. numberofstock > 25). Notice There's No Select Following.

however, If you change the last select clause to select p.name, the compiler will translate this LINQ statement into Product.where (p = P. numberofstock > 25). Select (p = = p.name).

Clause by

Get all product names in products, and the positive order (default) arrangement:

From P in products

ORDER BY P.name

Select P.name

Sql:select name from Products order by name

The ThenBy clause must always be followed by an After-an.

Let clause

Suppose you have one of the following queries:

            var  from inch Mycarsenum                  by car. Petname.length                        Select  car. petname;             foreach (var in Query)            {                Console.WriteLine ("{0}: {1}", Name.) Length, name);            }

We found that for Name. Length was quoted two Times. Can we introduce a temporary variable? The above query will be rewritten by the compiler to:

Mycarsenum.orderby (c = c.petname.length). Select (c = c.petname).

We can introduce a temporary variable using the Let Clause:

  var  query = from  car in   mycarsenum let length  = CAR.P                Etname.length  orderby   Length  select  new  {Name = car.            petname, length = length};  foreach  (var  name in   Query) {console.writeline (  " {0}: {1}  "  , Name. Length, Name.            Name); }

The above query will be rewritten by the compiler to:

Mycarsenum

. Select (car = new {car, length = car. Length})

. (c = C.length)

. Select (c = = new {Name = c.petname, Length = c.length}).

The Compiler's rewrite results can be obtained by linqpad.

here, we can see that anonymous types play a role in LINQ. Select New {Name = car. petname, length = length} (anonymous Type) allows us to get a new type effortlessly.

Connection

Examine the following two tables:

Table Defect:

Table Notificationsubscription:

We find that both tables have an outer code PROJECTID. So we can try to connect and see what Happens.

Using inner joins of join clauses

You must indicate which column is based on when you are connecting Inside. If we were to make an internal connection based on projectid, we could foresee that only 1 and 2 appeared for the ProjectID column of table defect, so the first and fourth rows of notificationsubscription would be in the result set, and the other two lines would be Absent.

Inquire:

             from inch Defects              inch notificationsubscriptions on                 defect. ProjectID equals Subscription. ProjectID            Selectnew {defect. Summary, Subscription. emailaddress}

If we reverse the table before and after the join clause, the result will be the same number of records, only in Order. LINQ will delay execution of the Connection. The sequence to the right of the join is cached and the left side is streamed: when execution starts, LINQ reads the entire right-hand sequence, and then does not need to read the right sequence again, and then begins iterating to the left Sequence. so if you want to connect a huge table and a very small table, try to put the small table on the Right.

The translation of the compiler is:

defects.join (      notificationsubscriptions,       = defect. projectid,       = Subscription. projectid,                 = =new           {            = defect. Summary,             = Subscription. EmailAddress         }   )
grouping connections using join into clauses

Inquire:

 from inch   in Notificationsubscriptionson defect. Project equals Subscription. Projectinto groupedsubscriptionsSelectnew {defect=defect, subscriptions= groupedsubscriptions}

The result will Be:

An important difference between an inner join and a grouped connection is that the number of results for a grouped connection must be the same as the number of records on the left table (for example, the table defects on the left of this example has 41 records, the number of results for a grouped connection must be 41), even if the records on the left table have no corresponding records on the right This is similar to the left outer join of Sql. As with an inner join, The grouping connection caches the sequence to the right, while the sequence on the left is Streamed.

The compiler translates to a simple call to the GroupJoin method:

defects.groupjoin (      notificationsubscriptions,       = defect. Project,       = Subscription. Project,       = =          new           {            = defect             ,=  Groupedsubscriptions         }   )
Using multiple from clauses for cross-multiplication

Inquire:

 from inch defectusers  from inch Projects Select New {user = user, Project = project}

There are 6 records in the Defectusers table and 3 records in the projects table, the result will be 18 strokes:

The compiler will interpret it as method selectmany:

defectusers.selectmany (      = = Projects       ,= =          new           {             = user,             = Project         }   )

Even if two tables are involved, the SelectMany approach is completely streaming: only one element in each sequence is processed at a time (in The example above, it is processed 18 times). SelectMany does not need to cache the right sequence, so it does not load a lot of content into memory at Once.

Make a selection between a query expression and a point marker

Many people love to use dot notation, which refers to calling LINQ query operators in plain C # instead of query Expressions. The dot tag is not an official Name. There are many arguments for the pros and cons of these two formulations:

    • Each query expression can be converted to the form of a point marker, which in turn is not necessarily. There are no equivalent query expressions for many LINQ operators, such as Reverse,sort and so On.
    • Since the point marker is the form after the query expression is compiled, using the dot tag saves you from compiling a Step.
    • Point markers are more readable than query expressions (not for Everyone)
    • The dot tag embodies the object-oriented nature, while inserting a SQL in C # makes people feel Nondescript.
    • The dot tag can be easily
    • Query expressions are simpler when joins, look more like sql, and dot-tagged joins are very difficult to understand
C # 3.0 All of the features presented are better for LINQ services

The following example uses a common delegate method to implement a WHERE (o = > 5):

 public Delegate BOOLPredicatedelegate (inti);  public Static voidMain (string[] Args) {            varSeq = Enumerable.range (0,9); varSeqwhere =Newlist<int>(); Predicatedelegate PD=Newpredicatedelegate (predicate); foreach(varIinchSeq) {                if(pd (I)) {seqwhere.add (i); }            }        }        //the Target predicate delegate         public Static BOOLpredicate (intInput) {            returnInput >5; }

Since where is a judgment, it returns a Boolean value, so we need a delegate of shape like func<int, bool>, so we can construct a method that takes an int and returns a bool in which to implement the Filter's Judgment. finally, the whole sequence is iterated, and the result is obtained by judging each of them. If you use linq, the entire process will be simplified to one sentence left.

The predicate of anonymous functions in C # 2.0 allows us to put the method Inline. If there is no anonymous function, you must write a delegate target method for each query.

 public Delegate BOOLPredicatedelegate (inti);  public Static voidMain (string[] Args) {            varSeq = Enumerable.range (0,9); varSeqwhere =Newlist<int>(); Predicatedelegate PD=Delegate(intInput) {                returnInput >5;            }; foreach(varIinchSeq) {                if(pd (I)) {seqwhere.add (i); }            }        }

C # is iterative in the where method, so we don't see Foreach. because where is an extension method of enumerable , you can use the Where method on the SEQ Object.

Sometimes we need to select a few columns from the database as the result, when the presence of the anonymous type makes it unnecessary to create a new type for these columns (unless they are often used, you may need a viewmodel layer at this point). the existence of implicit types makes it unnecessary to think about what type is obtained by a query statement (most of the time we don't care about its type), simply using var.

var seq = Enumerable.range (09);             var New             {                = o,                1            });

. NET Surface Question series [+]-LINQ to Object

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.