Practical notes for reading using LINQ-Chapter 1 goes beyond basic Memory Data Query

Source: Internet
Author: User

5.1.1 query non-generic Sets

If you have carefully read the previous chapters of this book, you should be able to query the set data in the memory using LINQ to objects. However, there is another problem, that is, we think that we can operate on all types of sets, but in fact we can only query part of the set types. The reason is that, during the design of LINQ to objects, it is used to implement the generic set type of the system. Collections. Generic. ienumerable <t> interface. Although. net Framework, including system. collections. generic. list <t>, array, dictionary, and queue all implement the ienumerable <t> interface, but the problem is that ienumerable <t> is a generic interface, but not all set types are generic.

In. NET 2.0, the concept of generics is introduced for the first time, but not everyone uses this function. Furthermore, even if your own code uses generics, you may still need to work with existing code that is not based on generics. For example, before the introduction of generics, the most common set type in the. NET Framework is system. Collections. arraylist.

Arraylist is not a generic set and does not implement the ienumerable <t> interface. Each element in arraylist is a weak object. Does this mean that LINQ cannot operate on arraylist? We can use the cast operator to build a bridge between a non-generic set and a standard query operator.

ArrayList books =GetArrayList(); var query = frombook in books.Cast<Book>()wherebook.PageCount>150select new {book.Title,book.Publisher.Name }; dataGridView.DataSource=query.ToList(); 

5.1.2 grouping by multiple conditions

Grouping by publishing house and subject

VaR query = frombook in sampledata. Books

Group book by new {book. Publisher, Book. Subject };

Use into keywords in the group by clause

var query = frombook in SampleData.Booksgroup book by new {book.Publisher,book.Subject }into grouping selectnew {       publisher = grouping.Key.Publisher.Name,       Subject = grouping.Key.Subject.Name,       Books = grouping};

The element types in each group are not necessarily the same as those in the original sequence. For example, we may only want to get the title of each book, rather than the entire book object. For example, you can group the titles of books by publishing houses and themes:

var query = from bookin SampleData.Booksgroup book.Title bynew { book.Publisher,book.Subject }into grouping selectnew {       Publisher = grouping.Key.Publisher.Name,       Subject = grouping.Key.Subject.Name,       Titles = grouping};

5.1.3 dynamic query

Custom sorting

Another common requirement is to sort the query results according to users' preferences. dynamic query is also required. In a query statement, the sorting condition can be specified by the orderby clause or the orderby operator. The following query expression sorts the books in the result by their titles:

from book inSampleData.Booksorderby book.Titleselect book.Title;

The same functions can be achieved using query operators:

SampleData.Books.Orderby(book=>book.Title).Select(book=>book.Title);

If you want to dynamically select a sorting condition, you can compile a method to receive the delegate of a sorting selector as a parameter. Then you can pass this parameter to the orderby operator. The signature of the orderby operator is as follows:

OrderedSequence<TElement>OrderBy<TElement,TKey>(thisIEnumerable<TElement> source,Func<TElement,TKey> keySelector)

From the code above, we can see that the parameter type received by the orderby operator is func <telement, tkey>. In our example, the element type in the source sequence is book, so telement is book type. The key type can be dynamically selected in the string (such as the title attribute) or certificate (such as the pagecount attribute. You can use the generic method to support both types of keys, where tkey is a type parameter.

You can use the following parameters to perform custom sorting:

voidCustomSort<TKey>(Func<Book,TKey> selector){       varbooks=SampleData.Books.OrderBy(selector);       ObjectDumper.Write(books);}

Use parameters in the query expression for custom sorting

void CustomSort<TKey>(Func<Book,TKey> selector){       var books=from book in SampleData.Books       orderby selector(book) select book;       ObjectDumper.Write(books);}

Use the following statement to call this method:

Customsort (Book => book. Title );

Or:

Customsort (Book => book. publisher. Name );

However, the preceding implementation does not support descending order. To add support for descending order, we can modify the existing method'

voidCustomSort<TKey>(Func<Book,TKey> selector,Boolean ascending){       IEnumerable<Book> books =SampleData.Books;       books = ascending?books.OrderBy(selector)                                   :books.OrderByDescending(selector);       ObjectDumper.Write(books);}

In this way, the customsort method can only be implemented by explicitly calling the query operator. The query expression cannot contain the judgment on the ascending parameter, because its orderby clause must be static.

This additional ascending parameter allows us to select between the orderby and orderbydescending operators. Use the following statement to sort the results in descending order instead of the default Ascending Order:

Customsort (Book => book. Title, false );

Create query statement based on user input

var query =SampleData.Books.Where(book=>book.PageCount>=(int)cbxPageCount.SelectedValue).Where(book=>book.Title.Contains(txtTitleFilter.Text)) if(cbxSortOrder.SelectedIndex==1)       query =query.OrderBy(book=>book.Title);elseif(cbxSortOrder.SelectedIndex==2)       query =query.OrderBy(book=>book.Publisher.Name);elseif(cbxSortOrder.SelectedIndex==3)       query =query.OrderBy(book=>book.PageCount); query =query.Select(book=>new{       book.Title,       book.PageCount,       publisher=book.Publisher.Name}); dataGridView1.DataSource=query.ToList();

To improve code reusability and readability, we 'd better move this query statement to a dedicated method.

voidConditionalQuery<TSortKey>(int minPageCount,String titleFilter,Func<Book,TSortKey>sortSelector){       var query = SampleData.Books       .Where(book=>book.PageCount>=minPageCount.Value)       .Where(book=>book.Title.Contains(txtTitleFilter))       .OrderBy(sortSelector)       .Select(book=>new{              book.Title,              book.PageCount,              Publisher=book.Publisher.Name});        dataGridView1.DataSource=query.ToList();}

Here we use the operator syntax for display, instead of the query expression, to prepare for the following er improvement. The preceding method can be called using the following method.

int? minPageCount;string titleFilter; minPageCount=(int?)cbxPageCount.SelectedValue;titleFilter =txtTitleFilter.Text;if(cbxSortOrder2.SelectedIndex==1){       ConditionalQuery(minPageCount,titleFilter,book=>book.Title);}elseif(cbxSortOrder2.SelectedIndex==2){       ConditionalQuery(minPageCount,titleFilter,book=>book.Publisher.Name);}elseif(cbxSortOrder2.SelectedIndex==3){       ConditionalQuery(minPageCount,titleFilter,book=>book.PageCount);}else{       ConditionalQuery(minPageCount,titleFilter,null);}

It looks good, but our program is not over yet-this query is not flexible enough. In fact, there is still a potential problem in the Code: if the user does not provide conditions, it will not get the correct result-the Program has not considered the conditions that are not limited.

We need to solve this problem and determine whether to add conditions before adding conditions. If you do not specify a condition, the program should ignore its related clauses.

The complete version of the conditionalquery method has considered whether the query condition is null.

voidConditionalQuery<TSortKey>(int? minPageCount,String titleFilter,Func<Book,TSortKey>sortSelector){       IEnumerable<Book> query;        query = SampleData.Books;       if(minPageCount.HasValue)              query =query.Where(book=>book.PageCount>=minPageCount.Value);       if(!String.IsNullOrEmpty(titleFilter))              query =query.Where(book=>book.Title.Contains(titleFilter));       if(sortSelector!=null)              query =query.OrderBy(sortSelector);             var completeQuery = query.Select(       book=>new{              book.Title,              book.PageCount,              Publisher=book.Publisher.Name});        dataGridView1.DataSource=completeQuery.ToList();}

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.