Hiển thị các bài đăng có nhãn LINQ. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn LINQ. Hiển thị tất cả bài đăng

Thứ Hai, 16 tháng 2, 2009

Làm thế nào để xXử lý ngoại lệ trong biểu thức truy vấn

Nó có thể gọi bất kỳ phương pháp trong bối cảnh của một biểu thức query. Tuy nhiên, chúng tôi khuyên bạn nên tránh gọi bất kỳ method trong một biểu thức query có thể tạo ra một tác dụng phụ chẳng hạn như thay đổi nội dung của nguồn dữ liệu hoặc throw một ngoại lệ. Ví dụ này cho thấy làm thế nào để tránh trường hợp ngoại lệ nâng cao khi bạn gọi phương thức trong một biểu thức query mà không vi phạm nói chung. NET Framework hướng dẫn về xử lý ngoại lệ. Những trạng thái hướng dẫn đó thì có thể bắt một ngoại lệ cụ thể khi bạn hiểu tại sao nó sẽ được ném ra trong một bối cảnh cụ thể.

Ví dụ sau đây cho thấy làm thế nào để di chuyển mã xử lý ngoại lệ bên ngoài một biểu thức query. Điều này chỉ có thể khi các method không phụ thuộc vào bất kỳ các biến local để truy vấn.

class ExceptionsOutsideQuery
{
      static void Main()
      {
            // DO THIS with a datasource that might
            // throw an exception. It is easier to deal with
            // outside of the query expression.
            IEnumerable dataSource;
            try
            {
                    dataSource = GetData();
            }
            catch (InvalidOperationException)
            {
                   // Handle (or don't handle) the exception
                   // in the way that is appropriate for your application.
                   Console.WriteLine("Invalid operation");
                   goto Exit;
            }
            // If we get here, it is safe to proceed.
            var query = from i in dataSource
            select i * i;
            foreach (var i in query)
                   Console.WriteLine(i.ToString());


            //Keep the console window open in debug mode
            Exit:
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
     }


      // A data source that is very likely to throw an exception!
      static IEnumerable GetData()
      {
            throw new InvalidOperationException();
      }
}

Trong một số trường hợp, câu trả lời tốt nhất để một ngoại lệ được thrown từ bên trong một query có thể để ngăn chặn việc thực hiện query ngay lập tức. Ví dụ sau đây cho thấy làm thế nào để xử lý các trường hợp ngoại lệ có thể được thrown từ bên trong một thân query. Giả sử rằng SomeMethodThatMightThrow khả năng có thể gây ra một ngoại lệ đòi hỏi phải thực hiện query để ngăn chặn.

Lưu ý rằng khối try bao bọc các vòng lặp foreach, và không phải là query chính nó. Điều này là do các vòng lặp foreach là điểm mà tại đó các truy vấn được thực thi.

class QueryThatThrows
{
        static void Main()
        {
                // Data source.
                string[] files = { "fileA.txt", "fileB.txt", "fileC.txt" };


                // Demonstration query that throws.
                var exceptionDemoQuery = from file in files
                       let n = SomeMethodThatMightThrow(file)
                       select n;


               // Runtime exceptions are thrown when query is executed.
               // Therefore they must be handled in the foreach loop.
               try
               {
                      foreach (var item in exceptionDemoQuery)
                      {
                              Console.WriteLine("Processing {0}", item);
                      }
                }


                // Catch whatever exception you expect to raise
                // and/or do any necessary cleanup in a finally block
                catch (InvalidOperationException e)
               {
                      Console.WriteLine(e.Message);
               }


               //Keep the console window open in debug mode
               Console.WriteLine("Press any key to exit");
               Console.ReadKey();
        }


         // Not very useful as a general purpose method.
         static string SomeMethodThatMightThrow(string s)
         {
               if (s[4] == 'C')
                     throw new InvalidOperationException();
               return @"C:\newFolder\" + s;
         }
}
/* Output:
Processing C:\newFolder\fileA.txt
Processing C:\newFolder\fileB.txt
Operation is not valid due to the current state of the object.
*/

DangTrung.

Làm thế nào để xử lý giá trị Null trong biểu thức truy vấn

Ví dụ này cho thấy làm thế nào để xử lý các giá trị null có thể có trong bộ sưu tập nguồn. Một bộ sưu tập các đối tượng đó như là một IEnumerable có thể chứa các yếu tố có giá trị null. Nếu nguồn là một bộ sưu tập vô giá trị hoặc có một phần tử có giá trị null, và query của bạn không xử lý các giá trị null, NullReferenceException sẽ được đẩy ra ngoài khi bạn thực hiện câu truy vấn.

Bạn có thể bảo vệ mã để tránh một ngoại lệ tham chiếu null như trong ví dụ sau đây:

var query1 =  from c in categories
       where c != null
       join p in products on c.ID equals
               (p == null ? null : p.CategoryID)
       select new { Category = c.Name, Name = p.Name };

Trong ví dụ trước, các nơi mệnh đề lọc ra tất cả các yếu tố null trong thứ tự danh mục. Kỹ thuật này được độc lập của việc kiểm tra null trong mệnh đề join. Các biểu thức điều kiện với null trong ví dụ này hoạt động bởi vì Products.CategoryID là kiểu int? đó là viết tắt cho Nullable.

Trong một mệnh đề join, nếu chỉ có một trong các phím so sánh là một loại giá trị nullable, bạn có thể bỏ các kia với một loại nullable trong biểu thức query. Trong ví dụ sau đây, giả sử là EmployeeID là một cột chứa giá trị kiểu int?:

void TestMethod(Northwind db)
{
       var query = from o in db.Orders
              join e in db.Employees
                     on o.EmployeeID equals (int?)e.EmployeeID
              select new { o.OrderID, e.FirstName };
}

DangTrung.

Làm thế nào để join bằng cách sử dụng Key Composite

Ví dụ này cho thấy làm thế nào để thực hiện join các hoạt động mà bạn muốn sử dụng nhiều hơn một khóa chính để xác định một trận đấu. Điều này được thực hiện bằng cách sử dụng một khóa composite. Bạn tạo một khóa composite như là một loại anonymous hoặc tên gõ với các giá trị mà bạn muốn so sánh. Nếu biến query sẽ được chuyển qua các biên giới, phương pháp sử dụng một loại có tên overrides Equals và GetHashCode cho khoá. Tên của các thuộc tính, và thứ tự mà chúng xảy ra, phải được giống hệt nhau trong mỗi khóa.

Ví dụ sau đây cho thấy làm thế nào để sử dụng một khóa composite để join dữ liệu từ ba bảng:

var query = from o in db.Orders from p in db.Products
       join d in db.OrderDetails on new {o.OrderID, p.ProductID} equals new {d.OrderID,
              d.ProductID} into details from d in details
       select new {o.OrderID, p.ProductID, d.UnitPrice};

Các khóa composite phụ thuộc vào tên của các thuộc tính trong các khóa, và thứ tự mà chúng xảy ra. Nếu các thuộc tính trong chuỗi nguồn không có tên giống nhau, bạn phải gán tên mới trong các khóa. Ví dụ, nếu bảng Orders và bảng OrderDetails từng được sử dụng tên khác nhau cho các cột của họ, bạn có thể tạo ra phím composite bằng cách chỉ định tên giống hệt nhau trong các loại anonymous:

join...on new {Name = o.CustomerName, ID = o.CustID} equals
        new {Name = d.CustName, ID = d.CustID }

DangTrung.

Chủ Nhật, 15 tháng 2, 2009

Làm thế nào để sắp xếp các kết quả của một Clause join

Ví dụ này cho thấy làm thế nào để sắp xếp các kết quả của một hoạt động join. Lưu ý rằng các lệnh được thực hiện sau khi join. Mặc dù bạn có thể sử dụng một mệnh đề orderby với một hoặc nhiều trình tự mã nguồn trước khi join, nhìn chung chúng takhông giới thiệu nó. Một số nhà cung cấp LINQ có thể không có duy trì lệnh sau khi join.

Truy vấn này tạo ra một group join, và sau đó sắp xếp các group dựa trên các yếu tố thể loại, mà vẫn còn trong phạm vi. Bên trong bộ khởi tạo kiểu anonymous, một sub query orhers tất cả các yếu tố kết hợp từ các chuỗi sản phẩm.

class HowToOrderJoins
{
       #region Data
       class Product
       {
              public string Name { get; set; }
              public int CategoryID { get; set; }
       }

       class Category
       {
              public string Name { get; set; }
              public int ID { get; set; }
       }

       // Specify the first data source.
       List categories = new List()
       {
               new Category(){Name="Beverages", ID=001},
               new Category(){ Name="Condiments", ID=002},
               new Category(){ Name="Vegetables", ID=003},
               new Category() { Name="Grains", ID=004},
               new Category() { Name="Fruit", ID=005}
       };

       // Specify the second data source.
       List products = new List()
       {
               new Product{Name="Cola", CategoryID=001},
               new Product{Name="Tea", CategoryID=001},
               new Product{Name="Mustard", CategoryID=002},
               new Product{Name="Pickles", CategoryID=002},
               new Product{Name="Carrots", CategoryID=003},
               new Product{Name="Bok Choy", CategoryID=003},
               new Product{Name="Peaches", CategoryID=005},
               new Product{Name="Melons", CategoryID=005},
       };
       #endregion
       
       static void Main()
       {
               HowToOrderJoins app = new HowToOrderJoins();
               app.OrderJoin1();

               // Keep console window open in debug mode.
               Console.WriteLine("Press any key to exit.");
               Console.ReadKey();
        }

        void OrderJoin1()
        {
                var groupJoinQuery2 =  from category in categories
                       join prod in products on category.ID equals prod.CategoryID into prodGroup
                       orderby category.Name
                       select new
                       {
                               Category = category.Name,
                               Products = from prod2 in prodGroup  orderby prod2.Name
                               select prod2
                       };
                foreach (var productGroup in groupJoinQuery2)
                {
                        Console.WriteLine(productGroup.Category);
                        foreach (var prodItem in productGroup.Products)
                        {
                                Console.WriteLine(" {0,-10} {1}", prodItem.Name, prodItem.CategoryID);
                         }
                 }
         }
        /* Output :
            Beverages
            Cola 1
            Tea 1
            Condiments
            Mustard 2
            Pickles 2
            Fruit
            Melons 5
            Peaches 5
            Grains
            Vegetables
            Bok Choy 3
            Carrots 3
         */
}
DangTrung.

Làm thế nào để sử dụng Left Outer Joins

Một left outer join là một join, trong đó mỗi phần tử của các bộ sưu tập đầu tiên được trả về, bất kể nó có bất kỳ yếu tố tương quan trong bộ sưu tập thứ hai. Bạn có thể sử dụng LINQ để thực hiện một left outer join bằng cách gọi DefaultIfEmpty kết quả của một group join.

Ví dụ sau đây cho thấy làm thế nào để sử dụng Methos DefaultIfEmpty kết quả của một group join để thực hiện một left outer join.

Bước đầu tiên trong việc tạo ra một left outer join trong hai bộ sưu tập là để thực hiện một bên join bằng cách sử dụng một group join. Trong ví dụ này, danh sách các đối tượng Person inner join vào danh sách các đối tượng PET dựa trên một Person object phù hợp với Pet.Owner.

Bước thứ hai là để bao gồm mỗi yếu tố của bộ sưu tập (left) đầu tiên trong tập hợp kết quả ngay cả khi không có yếu tố phù hợp trong bộ sưu tập phải. Điều này được thực hiện bằng cách gọi DefaultIfEmpty trên mỗi chuỗi kết hợp các yếu tố từ các group join. Trong ví dụ này, DefaultIfEmpty được gọi vào mỗi chuỗi các đối tượng phù hợp với PET. Nó trả về một bộ sưu tập có chứa một giá trị, mặc định duy nhất nếu các trình tự của các đối tượng phù hợp PET trống cho bất kỳ đối tượng Person, qua đó đảm bảo rằng kết quả mỗi đối tượng Person được đại diện trong bộ sưu tập.

class Person
{
       public string FirstName { get; set; }
       public string LastName { get; set; }
}

class Pet
{
       public string Name { get; set; }
       public Person Owner { get; set; }
}

public static void LeftOuterJoinExample()
{
       Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
       Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
       Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
       Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

       Pet barley = new Pet { Name = "Barley", Owner = terry };
       Pet boots = new Pet { Name = "Boots", Owner = terry };
       Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
       Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
       Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

       // Create two lists.
       List people = new List { magnus, terry, charlotte, arlene };
       List pets = new List { barley, boots, whiskers, bluemoon, daisy };

       var query = from person in people
              join pet in pets on person equals pet.Owner into gj
              from subpet in gj.DefaultIfEmpty()
              select new { 
                      person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name)      
              };

       foreach (var v in query)
       {
              Console.WriteLine("{0,-15}{1}", v.FirstName + ":", v.PetName);
       }
}

// This code produces the following output:
//
// Magnus: --- > Daisy
// Terry: --- > Barley
// Terry: --- >  Boots
// Terry: --- > Blue Moon
// Charlotte: --- > Whiskers
// Arlene: --- >
DangTrung

Làm thế nào để thực hiện Grouped Join

Các group join rất hữu ích cho tạo ra các cấu trúc phân cấp dữ liệu. Những cặp này mỗi yếu tố từ các bộ sưu tập đầu tiên với một tập hợp các yếu tố tương quan từ các bộ sưu tập thứ hai.

Ví dụ, một class hoặc cơ sở dữ liệu một bảng quan hệ có tên là Sinh viên có thể chứa hai lĩnh vực: Id và Name. Một class thứ hai hoặc bảng cơ sở dữ liệu quan hệ có tên là khóa học có thể có hai lĩnh vực: StudentId và CourseTitle. Một nhóm tham gia của hai nguồn dữ liệu, dựa trên kết hợp Student.Id và Course.StudentId, sẽ từng nhóm sinh viên với một bộ sưu tập của các đối tượng học.

Ví dụ đầu tiên trong chủ đề này cho bạn thấy làm thế nào để thực hiện một group join. Ví dụ thứ hai chỉ cho bạn cách sử dụng một nhóm join để tạo ra các phần tử XML.

Ví dụ Group Join :

Ví dụ sau đây thực hiện một nhóm join của các đối tượng của loại hình Person và PET dựa trên những người phù hợp với property Pet.Owner. Không giống như một group không join, mà sẽ tạo ra một cặp của các yếu tố cho mỗi trận đấu, các group join tạo ra chỉ có một kết quả là đối tượng cho từng thành phần của bộ sưu tập đầu tiên, mà trong ví dụ này là một đối tượng Person. Các yếu tố tương ứng từ các bộ sưu tập thứ hai, trong ví dụ này là Pet đối tượng, được nhóm lại thành một bộ sưu tập. Cuối cùng, chức năng kết quả chọn tạo ra một loại giấu tên cho mỗi trận đấu mà bao gồm Person.FirstName và một bộ sưu tập của các đối tượng Pet.

class Person
{
        public string FirstName { get; set; }
        public string LastName { get; set; }
}

class Pet
{
        public string Name { get; set; }
        public Person Owner { get; set; }
}

///
/// This example performs a grouped join.
///
public static void GroupJoinExample()
{
        Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
        Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
        Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
        Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

        Pet barley = new Pet { Name = "Barley", Owner = terry };
        Pet boots = new Pet { Name = "Boots", Owner = terry };
        Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
        Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
        Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

        // Create two lists.
        List people = new List { magnus, terry, charlotte, arlene };
        List pets = new List { barley, boots, whiskers, bluemoon, daisy };

        // Create a list where each element is an anonymous type
        // that contains the person's first name and a collection of
        // pets that are owned by them.
        var query = from person in people
                 join pet in pets on person equals pet.Owner into gj
                 select new { OwnerName = person.FirstName, Pets = gj };

        foreach (var v in query)
        {
               // Output the owner's name.
              Console.WriteLine("{0}:", v.OwnerName);
              // Output each of the owner's pet's names.
              foreach (Pet pet in v.Pets)
                    Console.WriteLine(" {0}", pet.Name);
        }
}
Group join rất lý tưởng cho việc tạo ra XML bằng cách sử dụng LINQ to XML. Ví dụ sau là tương tự như ví dụ trước, ngoại trừ thay vì tạo ra các loại giấu tên, chức năng chọn kết quả tạo ra các phần tử XML mà đại diện cho các đối tượng tham gia.

Bạn chỉ cần thay đổi dòng dưới cho ví dụ ở trên.

// Create XML to display the hierarchical organization of people and their pets.
XElement ownersAndPets = new XElement("PetOwners",
       from person in people join pet in pets on person equals pet.Owner into gj
                select new XElement("Person",
                        new XAttribute("FirstName", person.FirstName),
                        new XAttribute("LastName", person.LastName),
                        from subpet in gj
                            select new XElement("Pet", subpet.Name)));


Console.WriteLine(ownersAndPets);

DangTrung.

Thứ Bảy, 14 tháng 2, 2009

Làm thế nào nhóm Kết quả của contiguous keys

Ví dụ sau đây cho thấy làm thế nào để các nguyên tố nhóm thành nhiều phần đại diện cho subsequences của các contiguous keys. Ví dụ, giả sử rằng bạn có các trình tự sau đây của các cặp khóa có giá trị:
  • Key : A, A, A, B, C, A, B, B
  • Value : We, think, that, Linq, is, really, cool, !

Các nhóm sau đây sẽ được tạo ra theo thứ tự này:
  1. We, think, that
  2. Linq
  3. is
  4. really
  5. cool, !
Giải pháp này được thực hiện như là một phương pháp mở rộng đó là thread an toàn và trả về kết quả của nó một cách trực tuyến. Nói cách khác, nó tạo ra nhóm của nó khi nó di chuyển qua các dãy nguồn. Không giống như các nhà điều hành nhóm hay orderby, nó có thể bắt đầu trở lại nhóm người gọi trước khi tất cả các trình tự đã được đọc.

Chủ đề an toàn được thực hiện bằng cách làm một bản sao của từng nhóm hoặc từng đoạn theo trình tự được lặp lại nguồn, như được giải thích trong các ý kiến mã nguồn. Nếu dãy nguồn có một chuỗi lớn các mục liên tiếp, ngôn ngữ chung có thể bỏ một OutOfMemoryException.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ChunkIt
{
      // Static class to contain the extension methods.
      public static class MyExtensions
      {
              public static IEnumerable> ChunkBy(this  
                         IEnumerable source, Func keySelector)
              {
                      return source.ChunkBy(keySelector, EqualityComparer.Default);
              }

              public static IEnumerable> ChunkBy(this 
                         IEnumerable source, Func keySelector, 
                         IEqualityComparer comparer)
             {
                        // Flag to signal end of source sequence.
                        const bool noMoreSourceElements = true;

                        // Auto-generated iterator for the source array.
                        var enumerator = source.GetEnumerator();

                        // Move to the first element in the source sequence.
                        if (!enumerator.MoveNext()) yield break;

                        Chunk current = null;
                        while (true)
                        {
                               // Get the key for the current Chunk. The source iterator will churn through
                               // the source sequence until it finds an element with a key that doesn't match.
                               var key = keySelector(enumerator.Current);

                               // Make a new Chunk (group) object that initially has one 
                               // GroupItem, which is a copy of the current source element.
                               current = new Chunk(key, enumerator, value => 
                                               comparer.Equals(key, keySelector(value)));                              
                               yield return current;
                               if (current.CopyAllChunkElements() == noMoreSourceElements)
                               {
                                        yield break;
                               }
                       }
               }

               class Chunk : IGrouping
               {                       
                       // has a reference to the next ChunkItem in the list.
                       class ChunkItem
                       {
                                public ChunkItem(TSource value)
                                {
                                         Value = value;
                                }
                                public readonly TSource Value;
                                public ChunkItem Next = null;
                       }
                       // The value that is used to determine matching elements
                       private readonly TKey key;

                       // Stores a reference to the enumerator for the source sequence
                       private IEnumerator enumerator;

                       // A reference to the predicate that is used to compare keys.
                       private Func predicate;

                      // Stores the contents of the first source element that belongs with this chunk.
                      private readonly ChunkItem head;

                     // End of the list. It is repositioned each time a new. ChunkItem is added.
                     private ChunkItem tail;

                     // Flag to indicate the source iterator has reached the end of the source sequence.
                     internal bool isLastSourceElement = false;

                     // Private object for thread syncronization
                     private object m_Lock;

                    // REQUIRES: enumerator != null && predicate != null
                    public Chunk(TKey key, IEnumerator enumerator, 
                            Func predicate)
                    {
                            this.key = key;
                            this.enumerator = enumerator;
                            this.predicate = predicate;

                            // A Chunk always contains at least one element.
                            head = new ChunkItem(enumerator.Current);

                           // The end and beginning are the same until the list contains > 1 elements.
                           tail = head;

                           m_Lock = new object();
                    }

                   // Indicates that all chunk elements have been copied to the list of ChunkItems,
                   // and the source enumerator is either at the end, or else on an element with a new key.
                   // the tail of the linked list is set to null in the CopyNextChunkElement method if the
                  // key of the next element does not match the current chunk's key, or there are no more  
                  // elements in the source.
                  private bool DoneCopyingChunk { get { return tail == null; } }

                 // Adds one ChunkItem to the current group 
                 // REQUIRES: !DoneCopyingChunk && lock(this)
                 private void CopyNextChunkElement()
                 {
                         // Try to advance the iterator on the source sequence.
                         // If MoveNext returns false we are at the end, 
                         // and isLastSourceElement is set to true
                         isLastSourceElement = !enumerator.MoveNext();

                         // If we are (a) at the end of the source, or (b) at the end of the current chunk
                         // then null out the enumerator and predicate for reuse with the next chunk.
                         if (isLastSourceElement || !predicate(enumerator.Current))
                         {
                                 enumerator = null;
                                 predicate = null;
                         }
                         else
                         {
                                  tail.Next = new ChunkItem(enumerator.Current);
                         }

                        // tail will be null if we are at the end of the chunk elements
                        // This check is made in DoneCopyingChunk.
                        tail = tail.Next;
               }
               internal bool CopyAllChunkElements()
               {
                       while (true)
               {
               lock (m_Lock)
               {
                     if (DoneCopyingChunk)
                     {
                              // If isLastSourceElement is false,  it signals to the 
                              // outer iterator  to continue iterating.
                              return isLastSourceElement;
                     }
                     else
                     {
                             CopyNextChunkElement();
                      }
              }
       }
}


public TKey Key { get { return key; } }

// Invoked by the inner foreach loop. This method stays just one step ahead
// of the client requests. It adds the next element of the chunk only after
// the clients requests the last element in the list so far.
public IEnumerator GetEnumerator()
{
         //Specify the initial element to enumerate.
         ChunkItem current = head;

         // There should always be at least one ChunkItem in a Chunk.
               while (current != null)
              {
                       // Yield the current item in the list.
                       yield return current.Value;

                       // Copy the next item from the source sequence,
                       // if we are at the end of our local list.
                       lock (m_Lock)
                       {
                              if (current == tail)
                              {
                                      CopyNextChunkElement();
                              }
                       }
                       // Move to the next ChunkItem in the list.
                       current = current.Next;
                 }
           }

           System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
           {
                  return GetEnumerator();
           }
      }
}

       // A simple named type is used for easier viewing in the debugger. Anonymous types
       // work just as well with the ChunkBy operator.
       public class KeyValPair
       {
              public string Key { get; set; }
              public string Value { get; set; }
       }

       class Program
       {
              // The source sequence.
              public static IEnumerable list;

              // Query variable declared as class member to be available
              // on different threads.
              static IEnumerable> query;

              static void Main(string[] args)
              {
                    // Initialize the source sequence with an array initializer.
                    list = new[]
                    {
                          new KeyValPair{ Key = "A", Value = "We" },
                          new KeyValPair{ Key = "A", Value = "Think" },
                          new KeyValPair{ Key = "A", Value = "That" },
                          new KeyValPair{ Key = "B", Value = "Linq" },
                          new KeyValPair{ Key = "C", Value = "Is" },
                          new KeyValPair{ Key = "A", Value = "Really" },
                          new KeyValPair{ Key = "B", Value = "Cool" },
                          new KeyValPair{ Key = "B", Value = "!" }
                    };
                    // Create the query by using our user-defined query operator.
                    query = list.ChunkBy(p => p.Key);
                    // ChunkBy returns IGrouping objects, therefore a nested
                    // foreach loop is required to access the elements in each "chunk".
                    foreach (var item in query)
                    {
                          Console.WriteLine("Group key = {0}", item.Key);
                          foreach (var inner in item)
                          {
                                 Console.WriteLine("\t{0}", inner.Value);
                          }
                    }
                    Console.WriteLine("Press any key to exit");
                    Console.ReadKey();
              } 
       }
}

Để sử dụng Methos mở rộng trong dự án của bạn, sao chép các MyExtensions class Static vào một tập tin mã nguồn mới hoặc hiện tại và nếu nó là cần thiết, thêm một chỉ thị bằng cách sử dụng cho các namespace nơi mà nó được đặt.

 DangTrung.

Làm thế nào để thực hiện một Subquery vào một hoạt động Nhóm

Chủ đề này cho thấy hai cách khác nhau để tạo ra một truy vấn mà đơn đặt hàng dữ liệu nguồn thành các nhóm, và sau đó thực hiện một subquery trong mỗi nhóm riêng. Các kỹ thuật cơ bản trong mỗi ví dụ là nhóm các yếu tố nguồn bằng cách sử dụng một sự tiếp nối tên newGroup, và sau đó tạo ra một subquery mới chồng lên newGroup. Subquery này được chạy với từng nhóm mới được tạo ra bởi các truy vấn bên ngoài.

Lưu ý rằng trong ví dụ cụ thể kết quả cuối cùng không phải là một nhóm.

public void QueryMax()
{
       var queryGroupMax = from student in students
              group student by student.Year into studentGroup
              select new
              {
                      Level = studentGroup.Key,
                      HighestScore = (from student2 in studentGroup
                      select student2.ExamScores.Average()).Max()
              };
       int count = queryGroupMax.Count();
       Console.WriteLine("Number of groups = {0}", count);

       foreach (var item in queryGroupMax)
       {
               Console.WriteLine(" {0} Highest Score={1}", item.Level, item.HighestScore);
       }
}

DangTrung.

Làm thế nào để tạo ra các nhóm lồng nhau trong một biểu thức truy vấn LINQ

Ví dụ sau đây cho thấy làm thế nào để tạo ra các nhóm lồng nhau trong một biểu thức truy vấn LINQ. Mỗi nhóm được tạo ra theo năm học hoặc trình độ lớp sau đó được chia nhỏ thành các nhóm dựa trên tên của cá nhân.

public void QueryNestedGroups()
{
         var queryNestedGroups = from student in students  
                    group student by student.Year into newGroup1
                    from newGroup2 in
                           (from student in newGroup1  group student by student.LastName)
                    group newGroup2 by newGroup1.Key;


         // Three nested foreach loops are required to iterate
         // over all elements of a grouped group. Hover the mouse
         // cursor over the iteration variables to see their actual type.
         foreach (var outerGroup in queryNestedGroups)
         {
                 Console.WriteLine("DataClass.Student Level = {0}", outerGroup.Key);
                 foreach (var innerGroup in outerGroup)
                {
                        Console.WriteLine("\tNames that begin with: {0}", innerGroup.Key);
                        foreach (var innerGroupElement in innerGroup)
                       {
                               Console.WriteLine("\t\t{0} {1}", innerGroupElement.LastName, innerGroupElement.FirstName);
                       }
               }
        }
}

Lưu ý rằng ba vòng lặp foreach lồng nhau được yêu cầu phải duyệt qua các yếu tố bên trong của một nhóm lồng nhau.

DangTrung

Thứ Sáu, 13 tháng 2, 2009

Làm thế nào để Lưu trữ các kết quả của các truy vấn một trong bộ nhớ

Một truy vấn cơ bản là một tập hợp các hướng dẫn để làm thế nào để thu hồi và tổ chức dữ liệu. Để thực hiện các truy vấn yêu cầu một cuộc gọi đến method GetEnumerator của nó. Điều này được thực hiện khi bạn sử dụng một vòng lặp foreach để duyệt qua các yếu tố. Để lưu kết quả tại bất kỳ thời gian trước khi hoặc sau khi thực hiện vòng lặp, chỉ cần gọi một trong những method sau đây về các biến truy vấn:

  • ToList
  • ToArray
  • ToDictionary
  • ToLookup

Lưu Ý : khuyên rằng khi bạn lưu trữ các kết quả truy vấn, bạn chỉ định các đối tượng thu hồi lại với một biến mới như thể hiện trong ví dụ sau đây:

class StoreQueryResults
{
       static List numbers = new List() { 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
       static void Main()
       {
              IEnumerable queryFactorsOfFour = from num in numbers
                        where num % 4 == 0
                        select num;

             // Store the results in a new variable
             // without executing a foreach loop.
             List factorsofFourList = queryFactorsOfFour.ToList();

             // Iterate the list just to prove it holds data.
             foreach (int n in factorsofFourList)
             {
                     Console.WriteLine(n);
             }

             // Keep the console window open in debug mode.
             Console.WriteLine("Press any key");
             Console.ReadKey();
       }
}

DangTrung

Thứ Năm, 12 tháng 2, 2009

Làm thế nào để Group quả truy vấn

Group là một trong những khả năng mạnh nhất của LINQ. Các ví dụ sau đây cho thấy làm thế nào để Group dữ liệu theo những cách khác nhau:
  • Theo một property duy nhất.
  • Bằng một letter đầu tiên của một chuỗi property.
  • Bằng một loạt các số tính toán.
  • Bằng cách thể hiện khác Boolean.
  • Bởi một compound quan trọng.

Ngoài ra, hai câu truy vấn cuối cùng kết quả là một loại vô danh mới mà chỉ có họ và tên của học sinh.

public class StudentClass
{
        #region data
        protected enum GradeLevel { FirstYear = 1, SecondYear, ThirdYear, FourthYear };
        protected class Student
        {
                 public string FirstName { get; set; }
                 public string LastName { get; set; }
                 public int ID { get; set; }
                 public GradeLevel Year;
                 public List ExamScores;
         }

        protected static List students = new List
        {
                 new Student {FirstName = "Terry", LastName = "Adams", ID = 120,
                        Year = GradeLevel.SecondYear,
                        ExamScores = new List{ 99, 82, 81, 79}},
                 new Student {FirstName = "Fadi", LastName = "Fakhouri", ID = 116,
                        Year = GradeLevel.ThirdYear,
                        ExamScores = new List{ 99, 86, 90, 94}},
                 new Student {FirstName = "Hanying", LastName = "Feng", ID = 117,
                        Year = GradeLevel.FirstYear,
                        ExamScores = new List{ 93, 92, 80, 87}},
                 new Student {FirstName = "Cesar", LastName = "Garcia", ID = 114,
                        Year = GradeLevel.FourthYear,
                        ExamScores = new List{ 97, 89, 85, 82}},
                 new Student {FirstName = "Debra", LastName = "Garcia", ID = 115,
                        Year = GradeLevel.ThirdYear,
                        ExamScores = new List{ 35, 72, 91, 70}},
                new Student {FirstName = "Hugo", LastName = "Garcia", ID = 118,
                        Year = GradeLevel.SecondYear,
                        ExamScores = new List{ 92, 90, 83, 78}},
                new Student {FirstName = "Sven", LastName = "Mortensen", ID = 113,
                        Year = GradeLevel.FirstYear,
                        ExamScores = new List{ 88, 94, 65, 91}},
                new Student {FirstName = "Claire", LastName = "O'Donnell", ID = 112,
                       Year = GradeLevel.FourthYear,
                       ExamScores = new List{ 75, 84, 91, 39}},
                new Student {FirstName = "Svetlana", LastName = "Omelchenko", ID = 111,
                       Year = GradeLevel.SecondYear,
                       ExamScores = new List{ 97, 92, 81, 60}},
                new Student {FirstName = "Lance", LastName = "Tucker", ID = 119,
                       Year = GradeLevel.ThirdYear,
                       ExamScores = new List{ 68, 79, 88, 92}},
                new Student {FirstName = "Michael", LastName = "Tucker", ID = 122,
                       Year = GradeLevel.FirstYear,
                       ExamScores = new List{ 94, 92, 91, 91}},
                new Student {FirstName = "Eugene", LastName = "Zabokritski", ID = 121,
                       Year = GradeLevel.FourthYear,
                       ExamScores = new List{ 96, 85, 91, 60}}
        };
        #endregion

        //Helper method, used in GroupByRange.
        protected static int GetPercentile(Student s)
        {
                 double avg = s.ExamScores.Average();
                 return avg > 0 ? (int)avg / 10 : 0;
         }

         public void QueryHighScores(int exam, int score)
         {
                var highScores = from student in students
                where student.ExamScores[exam] > score
                select new {Name = student.FirstName, Score = student.ExamScores[exam]};
                foreach (var item in highScores)
               {
                      Console.WriteLine("{0,-15}{1}", item.Name, item.Score);
               }
        }
}

public class Program
{
        public static void Main()
        {
                StudentClass sc = new StudentClass();
                sc.QueryHighScores(1, 90);

                // Keep the console window open in debug mode.
                Console.WriteLine("Press any key to exit");
                Console.ReadKey();
       }
}

DangTrung

Thứ Tư, 11 tháng 2, 2009

Làm thế nào return một truy vấn từ một Method

Ví dụ này cho thấy làm thế nào để trả về một truy vấn từ một method như là giá trị trả về và như là một tham số ra.

Bất kỳ truy vấn phải có một loại IEnumerable hoặc IEnumerable, hoặc một loại có nguồn gốc như IQueryable. Vì vậy bất kỳ giá trị trả lại hoặc tham số trong một phương thức trả về một truy vấn cũng phải có kiểu. Nếu một phương thức materializes một truy vấn vào một List hoặc Array, nó được coi là trả lại kết quả truy vấn thay vì truy vấn chính nó. Một biến truy vấn đó được trả về từ method vẫn có thể được cấu tạo hoặc sửa đổi.

Trong ví dụ sau đây, Method đầu tiên trả về câu truy vấn như là một giá trị, và Method thứ hai, một truy vấn như là một tham số ra. Lưu ý rằng trong cả hai trường hợp, nó là một truy vấn được trả về, không kết quả truy vấn.

class MQ
{
       // QueryMethhod1 returns a query as its value.
       IEnumerable QueryMethod1(ref int[] ints)
       {
              var intsToStrings = from i in ints where i > 4 select i.ToString();
              return intsToStrings;
       }

       // QueryMethod2 returns a query as the value of parameter returnQ.
       void QueryMethod2(ref int[] ints, out IEnumerable returnQ)
       {
              var intsToStrings = from i in ints where i < 4 select i.ToString();
              returnQ = intsToStrings;
        }

        static void Main()
        {
               MQ app = new MQ();
               int[] nums = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

               // QueryMethod1 returns a query as the value of the method.
               var myQuery1 = app.QueryMethod1(ref nums);

               // Query myQuery1 is executed in the following foreach loop.
               Console.WriteLine("Results of executing myQuery1:");

               // Rest the mouse pointer over myQuery1 to see its type.
               foreach (string s in myQuery1)
               {
                      Console.WriteLine(s);
               }

               // You also can execute the query returned from QueryMethod1
              // directly, without using myQuery1.
              Console.WriteLine("\nResults of executing myQuery1 directly:");

             // Rest the mouse pointer over the call to QueryMethod1 to see its return type.
             foreach (string s in app.QueryMethod1(ref nums))
             {
                       Console.WriteLine(s);
             }
             IEnumerable myQuery2;

             // QueryMethod2 returns a query as the value of its out parameter.
             app.QueryMethod2(ref nums, out myQuery2);

             // Execute the returned query.
             Console.WriteLine("\nResults of executing myQuery2:");
             foreach (string s in myQuery2)
             {
                     Console.WriteLine(s);
             }

             // You can modify a query by using query composition. A saved query
             // is nested inside a new query definition that revises the results of the first query.
             myQuery1 = from item in myQuery1 orderby item descending select item;

             // Execute the modified query.
             Console.WriteLine("\nResults of executing modified myQuery1:");
             foreach (string s in myQuery1)
             {
                       Console.WriteLine(s);
             }

             // Keep console window open in debug mode.
             Console.WriteLine("Press any key to exit.");
             Console.ReadKey();
      }
}

DangTrung.

Thứ Ba, 10 tháng 2, 2009

Làm thế nào để thực hiện Inner Join (C#)

Trong điều kiện cơ sở dữ liệu quan hệ, một bên tham gia sản xuất một tập kết quả, trong đó mỗi phần tử của các bộ sưu tập đầu tiên xuất hiện một lần cho tất cả các yếu tố phù hợp trong bộ sưu tập thứ hai. Nếu một thành phần trong bộ sưu tập đầu tiên không có các yếu tố phù hợp, nó không xuất hiện trong tập kết quả. Các phương pháp tham gia, được gọi là do tham gia điều khoản trong C#, thực hiện một nội tâm tham gia.

Chủ đề này cho bạn thấy làm thế nào để thực hiện bốn biến thể của một bên tham gia:
  • Một đơn giản bên tham gia có tương quan các yếu tố từ hai nguồn dữ liệu dựa trên một khóa đơn giản.
  • Một trong những yếu tố tham gia có tương quan từ hai nguồn dữ liệu dựa trên một khóa composite. Một chính tổng hợp, mà là một chính mà bao gồm nhiều hơn một giá trị, cho phép bạn tương quan các yếu tố dựa trên nhiều hơn một tài sản.
  • Một đa tham gia, trong đó tiếp tham gia các hoạt động được nối với nhau.
  • Một trong tham gia được thực hiện bằng cách sử dụng một nhóm tham gia.

Ví dụ về Simple Key Join :
Ví dụ sau tạo ra hai bộ sưu tập có chứa các đối tượng của hai kiểu người dùng định nghĩa, người và vật nuôi. Truy vấn này sử dụng mệnh đề join trong C# để phù hợp với nhân vật với các đối tượng mà chủ Pet là người. Các mệnh đề select trong C# định nghĩa cách sẽ xem xét các kết quả đối tượng. Trong ví dụ này, các kết quả đối tượng là loại vô danh đó bao gồm tên của chủ sở hữu và tên của vật nuôi.

class Person
{
       public string FirstName { get; set; }
       public string LastName { get; set; }
}


class Pet
{
       public string Name { get; set; }
       public Person Owner { get; set; }
}


///
/// Simple inner join.
///

public static void InnerJoinExample()
{
       Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
       Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
       Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
       Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };
       Person rui = new Person { FirstName = "Rui", LastName = "Raposo" };


       Pet barley = new Pet { Name = "Barley", Owner = terry };
       Pet boots = new Pet { Name = "Boots", Owner = terry };
       Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
       Pet bluemoon = new Pet { Name = "Blue Moon", Owner = rui };
       Pet daisy = new Pet { Name = "Daisy", Owner = magnus };


       // Create two lists.
       List people = new List { magnus, terry, charlotte, arlene, rui };
       List pets = new List { barley, boots, whiskers, bluemoon, daisy };


       // Create a collection of person-pet pairs. Each element in the collection
       // is an anonymous type containing both the person's name and their pet's name.
       var query = from person in people join pet in pets on person equals pet.Owner
            select new { OwnerName = person.FirstName, PetName = pet.Name };


       foreach (var ownerAndPet in query)
       {
             Console.WriteLine("\"{0}\" is owned by {1}", ownerAndPet.PetName, 
                     ownerAndPet.OwnerName);
       }
}


// This code produces the following output:
// "Daisy" is owned by Magnus
// "Barley" is owned by Terry
// "Boots" is owned by Terry
// "Whiskers" is owned by Charlotte
// "Blue Moon" is owned by Rui

Ví dụ về Composite Key Join :
Ví dụ sau đây sử dụng một danh sách các đối tượng lao động và danh sách các đối tượng sinh viên để xác định các nhân viên cũng được học sinh. Cả hai loại có FirstName và sở hữu một LastName kiểu String. Các chức năng đó tạo ra các khoá kết nối từ các yếu tố của mỗi danh sách trả về một kiểu nặc danh mà bao gồm các tài sản FirstName và LastName của mỗi phần tử. Các hoạt động tham gia so sánh các tổ hợp phím bình đẳng và trả về cặp của các đối tượng từ danh sách mỗi nơi cả hai cái tên đầu tiên và tên những trận đấu cuối cùng.
class Employee
{
      public string FirstName { get; set; }
      public string LastName { get; set; }
      public int EmployeeID { get; set; }
}


class Student
{
      public string FirstName { get; set; }
      public string LastName { get; set; }
      public int StudentID { get; set; }
}


///
/// Performs a join operation using a composite key.
///

public static void CompositeKeyJoinExample()
{
      // Create a list of employees.
      List employees = new List {
            new Employee { FirstName = "Terry", LastName = "Adams", EmployeeID = 522459 },
            new Employee { FirstName = "Charlotte", LastName = "Weiss", EmployeeID = 204467 },
            new Employee { FirstName = "Magnus", LastName = "Hedland", EmployeeID = 866200 },
            new Employee { FirstName = "Vernette", LastName = "Price", EmployeeID = 437139 } 
      };


      // Create a list of students.
      List students = new List {
            new Student { FirstName = "Vernette", LastName = "Price", StudentID = 9562 },
            new Student { FirstName = "Terry", LastName = "Earls", StudentID = 9870 },
            new Student { FirstName = "Terry", LastName = "Adams", StudentID = 9913 } 
      };
      // Join the two data sources based on a composite key consisting of first and last name,
      // to determine which employees are also students.
      IEnumerable query = from employee in employees join student in students
               on new { employee.FirstName, employee.LastName }
               equals new { student.FirstName, student.LastName }
               select employee.FirstName + " " + employee.LastName;


      Console.WriteLine("The following people are both employees and students:");
      foreach (string name in query)
              Console.WriteLine(name);
      }


// This code produces the following output:
//
// The following people are both employees and students:
// Terry Adams
// Vernette Price

Ví dụ về Multiple Join :

class Person
{
      public string FirstName { get; set; }
      public string LastName { get; set; }
}


class Pet
{
      public string Name { get; set; }
      public Person Owner { get; set; }
}


class Cat : Pet { }


class Dog : Pet { }


public static void MultipleJoinExample()
{
      Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
      Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
      Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
      Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };
      Person rui = new Person { FirstName = "Rui", LastName = "Raposo" };
      Person phyllis = new Person { FirstName = "Phyllis", LastName = "Harris" };


      Cat barley = new Cat { Name = "Barley", Owner = terry };
      Cat boots = new Cat { Name = "Boots", Owner = terry };
      Cat whiskers = new Cat { Name = "Whiskers", Owner = charlotte };
      Cat bluemoon = new Cat { Name = "Blue Moon", Owner = rui };
      Cat daisy = new Cat { Name = "Daisy", Owner = magnus };


      Dog fourwheeldrive = new Dog { Name = "Four Wheel Drive", Owner = phyllis };
      Dog duke = new Dog { Name = "Duke", Owner = magnus };
      Dog denim = new Dog { Name = "Denim", Owner = terry };
      Dog wiley = new Dog { Name = "Wiley", Owner = charlotte };
      Dog snoopy = new Dog { Name = "Snoopy", Owner = rui };
      Dog snickers = new Dog { Name = "Snickers", Owner = arlene };


      // Create three lists.
      List people = new List { magnus, terry, charlotte, arlene, rui, phyllis };
      List cats = new List { barley, boots, whiskers, bluemoon, daisy };
      List dogs = new List { fourwheeldrive, duke, denim, wiley, snoopy, snickers };


      // The first join matches Person and Cat.Owner from the list of people and
     // cats, based on a common Person. The second join matches dogs whose names start
     // with the same letter as the cats that have the same owner.
     var query = from person in people join cat in cats on person equals cat.Owner
           join dog in dogs on new { Owner = person, Letter = cat.Name.Substring(0, 1) }
          equals new { dog.Owner, Letter = dog.Name.Substring(0, 1) }
          select new { CatName = cat.Name, DogName = dog.Name };


      foreach (var obj in query)
      {
           Console.WriteLine( "The cat \"{0}\" shares a house, and the first letter of their name, with  \"{1}\".", obj.CatName, obj.DogName);
      }
}


// This code produces the following output:
//
// The cat "Daisy" shares a house, and the first letter of their name, with "Duke".
// The cat "Whiskers" shares a house, and the first letter of their name, with "Wiley".

Inner Join bằng cách sử dụng Grouped Join
class Person
{
        public string FirstName { get; set; }
        public string LastName { get; set; }
}


class Pet
{
        public string Name { get; set; }
        public Person Owner { get; set; }
}


///
/// Performs an inner join by using GroupJoin().
///

public static void InnerGroupJoinExample()
{
       Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
       Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
       Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
       Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };


       Pet barley = new Pet { Name = "Barley", Owner = terry };
       Pet boots = new Pet { Name = "Boots", Owner = terry };
       Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
       Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
       Pet daisy = new Pet { Name = "Daisy", Owner = magnus };


       // Create two lists.
       List people = new List { magnus, terry, charlotte, arlene };
       List pets = new List { barley, boots, whiskers, bluemoon, daisy };


       var query1 = from person in people join pet in pets on person equals pet.Owner into gj
             from subpet in gj select new { OwnerName = person.FirstName, PetName = subpet.Name };


       Console.WriteLine("Inner join using GroupJoin():");
       foreach (var v in query1)
       {
                Console.WriteLine("{0} - {1}", v.OwnerName, v.PetName);
       }


      var query2 = from person in people  join pet in pets on person equals pet.Owner
              select new { OwnerName = person.FirstName, PetName = pet.Name };


      Console.WriteLine("\nThe equivalent operation using Join():");
      foreach (var v in query2) 
      {
            Console.WriteLine("{0} - {1}", v.OwnerName, v.PetName);
     }


// This code produces the following output:
//
// Inner join using GroupJoin():
// Magnus - Daisy
// Terry - Barley
// Terry - Boots
// Terry - Blue Moon
// Charlotte - Whiskers
//
// The equivalent operation using Join():
// Magnus - Daisy
// Terry - Barley
// Terry - Boots
// Terry - Blue Moon
// Charlotte - Whiskers

DangTrung.

Chủ Nhật, 8 tháng 2, 2009

Từ khoá truy vấn trong LINQ (Query Keywords)

Bảng liệt kê các từ khóa sử dụng trong biểu thức truy vấn trong.
  • FROM : Chỉ định một nguồn dữ liệu và biến một phạm vi (tương tự như một biến lặp đi lặp lại).
  • WHERE : Bộ lọc các yếu tố nguồn dựa trên một hoặc nhiều biểu thức Boolean cách nhau bởi logic AND OR điều hành (&& hoặc | |).
  • SELECT : Chỉ định kiểu và hình dạng mà các phần tử trong chuỗi trở về sẽ có khi truy vấn được thực hiện.
  • GROUP : Nhóm kết quả truy vấn theo một giá trị chính quy định.
  • INTO : Cung cấp một định danh có thể phục vụ như là một tham chiếu đến các kết quả của một nhóm tham gia, hoặc điều khoản lựa chọn.
  • ORDERBY : Phân loại các kết quả truy vấn trong tăng hay giảm dựa trên Comparer mặc định cho các loại nguyên tố.
  • JOIN : tham gia của hai nguồn dữ liệu dựa trên sự so sánh bình đẳng giữa hai tiêu chuẩn quy định phù hợp.
  • LET : giới thiệu một loạt biến để lưu trữ phụ biểu kết quả trong một biểu thức truy vấn.
  • IN : theo ngữ cảnh từ khoá trong một gia khoản.
  • ON : theo ngữ cảnh từ khoá trong một gia khoản.
  • EQUALS : theo ngữ cảnh từ khoá trong một gia khoản.
  • BY: theo ngữ cảnh từ khoá trong một điều khoản nhóm.
  • ASCENDING : từ khóa theo ngữ cảnh trong một khoản orderby.
  • DESXENDING : từ khóa theo ngữ cảnh trong một khoản orderby.

Example :

FROM :
class LowNums
{
        static void Main()
        {
               // A simple data source.
               int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
               // Create the query.
               // lowNums is an IEnumerable
               var lowNums = from num in numbers where num < 5 select num;


              // Execute the query.
              foreach (int i in lowNums)
              {
                     Console.Write(i + " ");
              }
       }
}
// Output: 4 1 3 2 0

WHERE :
class WhereSample2
{
        static void Main()
       {
               // Data source.
               int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
               // Create the query with two predicates in where clause.
               var queryLowNums2 =  from num in numbers where num < 5 && num % 2 == 0
                     select num;
               // Execute the query
               foreach (var s in queryLowNums2)
              {
                    Console.Write(s.ToString() + " ");
              }
      }
}
// Output: 4 2 0

GROUP :
// Query variable is an IEnumerable>
var studentQuery1 = from student in students group student by student.Last[0];

INTO :
class IntoSample1
{
         static void Main()
         {
                // Create a data source.
                string[] words = {"apples","blueberries","oranges","bananas","apricots"};
               // Create the query.
               var wordGroups1 = from w in words group w by w[0] into fruitGroup
                      where fruitGroup.Count() >= 2
                      select new { FirstLetter = fruitGroup.Key, Words = fruitGroup.Count() };
              // Execute the query. Note that we only iterate over the groups,
              // not the items in each group
              foreach (var item in wordGroups1)
              {
                     Console.WriteLine(" {0} has {1} elements.", item.FirstLetter, item.Words);
              }

              // Keep the console window open in debug mode
              Console.WriteLine("Press any key to exit.");
              Console.ReadKey();
       }
}
/* Output:
a has 2 elements.
b has 2 elements.
*/

DangTrung.

Thứ Bảy, 7 tháng 2, 2009

Mệnh đề Select trong LINQ (C#)

Trong một biểu thức truy vấn, các mệnh đề select quy định các loại giá trị đó sẽ được trình bày khi truy vấn được thực hiện. Kết quả là dựa trên đánh giá của tất cả các mệnh đề trước và trên bất kỳ các biểu thức trong mệnh đề tự chọn. Một biểu thức truy vấn phải chấm dứt với cả một mệnh đề select hoặc một mệnh đề group.

Ví dụ sau đây cho thấy một mệnh đề select đơn giản trong một biểu thức truy vấn.

class SelectSample1
{
       static void Main()
       {
              //Create the data source
              List Scores = new List() { 97, 92, 81, 60 };


              // Create the query.
              IEnumerable queryHighScores = from score in Scores
                         where score < 80 select score;


             // Execute the query.
             foreach (int i in queryHighScores)
             {
                    Console.Write(i + " ");
             }
      }
}
//Output: 97 92 81

Ví dụ sau đây cho thấy tất cả các hình thức khác nhau mà một mệnh đề select có thể mất. Trong mỗi truy vấn, lưu ý các mối quan hệ giữa các mệnh đề select và loại biến truy vấn (studentQuery1, studentQuery2, vv).

class SelectSample2
{
        // Define some classes
        public class Student
        {
                 public string First { get; set; }
                 public string Last { get; set; }
                 public int ID { get; set; }
                 public List Scores;
                 public ContactInfo GetContactInfo(SelectSample2 app, int id)
                 {
                         ContactInfo cInfo = (from ci in app.contactList  where ci.ID == id select ci)
                                       .FirstOrDefault();
                         return cInfo;
                 }


                 public override string ToString()
                 {
                         return First + " " + Last + ":" + ID;
                 }
        }


        public class ContactInfo
        {
                public int ID { get; set; }
                public string Email { get; set; }
                public string Phone { get; set; }
                public override string ToString() { return Email + "," + Phone; }
         }


         public class ScoreInfo
         {
                 public double Average { get; set; }
                 public int ID { get; set; }
         }


         // The primary data source
         List students = new List()
         {
                  new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List() {97, 92, 81, 60}},
                  new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List() {75, 84, 91, 39}},
                  new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List() {88,  94, 65, 91}},
                  new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List() {97, 89, 85, 82}},
         };


         // Separate data source for contact info.
         List<ContactInfo> contactList = new List()
         {
                new ContactInfo {ID=111, Email="SvetlanO@Contoso.com", Phone="206-555-0108"},
                new ContactInfo {ID=112, Email="ClaireO@Contoso.com", Phone="206-555-0298"},
                new ContactInfo {ID=113, Email="SvenMort@Contoso.com", Phone="206-555-1130"},
                new ContactInfo {ID=114, Email="CesarGar@Contoso.com", Phone="206-555-0521"}
         };



         static void Main(string[] args)
         {
                  SelectSample2 app = new SelectSample2();
                  // Produce a filtered sequence of unmodified Students.
                  IEnumerable studentQuery1 = from student in app.students
                      where student.ID > 111 select student;


                  Console.WriteLine("Query1: select range_variable");
                  foreach (Student s in studentQuery1)
                  {
                          Console.WriteLine(s.ToString());
                   }


                   // Produce a filtered sequence of elements that contain
                  // only one property of each Student.
                  IEnumerable studentQuery2 =  from student in app.students
                       where student.ID > 111 select student.Last;


                  Console.WriteLine("\r\n studentQuery2: select range_variable.Property");
                  foreach (string s in studentQuery2)
                  {
                         Console.WriteLine(s);
                  }


                  // Produce a filtered sequence of objects created by
                  // a method call on each Student.
                  IEnumerable studentQuery3 = from student in app.students
                        where student.ID > 111  select student.GetContactInfo(app, student.ID);


                  Console.WriteLine("\r\n studentQuery3: select range_variable.Method");
                  foreach (ContactInfo ci in studentQuery3)
                  {
                         Console.WriteLine(ci.ToString());
                  }


                 // Produce a filtered sequence of ints from
                 // the internal array inside each Student.
                 IEnumerable studentQuery4 = from student in app.students
                        where student.ID > 111 select student.Scores[0];


                 Console.WriteLine("\r\n studentQuery4: select range_variable[index]");
                 foreach (int i in studentQuery4)
                 {
                            Console.WriteLine("First score = {0}", i);
                 }


                 // Produce a filtered sequence of doubles
                 // that are the result of an expression.
                 IEnumerable studentQuery5 = from student in app.students
                       where student.ID > 111 select student.Scores[0] * 1.1;


                 Console.WriteLine("\r\n studentQuery5: select expression");
                 foreach (double d in studentQuery5)
                 {
                         Console.WriteLine("Adjusted first score = {0}", d);
                 }


                 // Produce a filtered sequence of doubles that are
                 // the result of a method call.
                 IEnumerable studentQuery6 = from student in app.students
                        where student.ID > 111 select student.Scores.Average();


                 Console.WriteLine("\r\n studentQuery6: select expression2");
                 foreach (double d in studentQuery6)
                 {
                          Console.WriteLine("Average = {0}", d);
                 }


                // Produce a filtered sequence of anonymous types
                // that contain only two properties from each Student.
                var studentQuery7 = from student in app.students where student.ID > 111
                        select new { student.First, student.Last };


                Console.WriteLine("\r\n studentQuery7: select new anonymous type");
                foreach (var item in studentQuery7)
                {
                        Console.WriteLine("{0}, {1}", item.Last, item.First);
                 }


                 // Produce a filtered sequence of named objects that contain
                 // a method return value and a property from each Student.
                 // Use named types if you need to pass the query variable
                 // across a method boundary.
                 IEnumerable studentQuery8 = from student in app.students
                        where student.ID > 111 select new ScoreInfo
                        {
                               Average = student.Scores.Average(),
                               ID = student.ID
                        };


                 Console.WriteLine("\r\n studentQuery8: select new named type");
                 foreach (ScoreInfo si in studentQuery8)
                 {
                       Console.WriteLine("ID = {0}, Average = {1}", si.ID, si.Average);
                 }


                 // Produce a filtered sequence of students who appear on a contact list
                 // and whose average is greater than 85.
                IEnumerable studentQuery9 = from student in app.students
                        where student.Scores.Average() > 85 
                        join ci in app.contactList on student.ID equals ci.ID select ci;


                Console.WriteLine("\r\n studentQuery9: select result of join clause");
                foreach (ContactInfo ci in studentQuery9)
                {
                        Console.WriteLine("ID = {0}, Email = {1}", ci.ID, ci.Email);
                }


               // Keep the console window open in debug mode
               Console.WriteLine("Press any key to exit.");
               Console.ReadKey();
       }
}
/* Output
Query1: select range_variable
Claire O'Donnell:112
Sven Mortensen:113
Cesar Garcia:114


studentQuery2: select range_variable.Property
O'Donnell
Mortensen
Garcia


studentQuery3: select range_variable.Method
ClaireO@Contoso.com,206-555-0298
SvenMort@Contoso.com,206-555-1130
CesarGar@Contoso.com,206-555-0521


studentQuery4: select range_variable[index]
First score = 75
First score = 88
First score = 97


studentQuery5: select expression
Adjusted first score = 82.5
Adjusted first score = 96.8
Adjusted first score = 106.7


studentQuery6: select expression2
Average = 72.25
Average = 84.5
Average = 88.25


studentQuery7: select new anonymous type
O'Donnell, Claire
Mortensen, Sven
Garcia, Cesar


studentQuery8: select new named type
ID = 112, Average = 72.25
ID = 113, Average = 84.5
ID = 114, Average = 88.25


studentQuery9: select result of join clause
ID = 114, Email = CesarGar@Contoso.com
*/

DangTrung.