2011-11-11 26 views
5

tôi đã cố gắng lấy một bản ghi và bỏ qua phần còn lại khác. mã của tôi không ném bất kỳ lỗi nào nhưng không đưa ra bất kỳ đầu ra nào. đây là mã của tôi. vì vậy xin vui lòng có một cái nhìn và cho tôi biết những gì là sai trong mã của tôi.LINQ Cách lấy một bản ghi và bỏ qua phần còn lại C#

public sealed class Person 
{ 
    public Person() { } 
    public Person(string name,bool HQ) { 
     this.Name = name; 
     this.HQ = HQ; 
    } 

    private string _Name; 
    public string Name 
    { 
     get { return _Name; } 
     set { _Name = value; } 
    } 

    private bool _HQ; 
    public bool HQ 
    { 
     get { return _HQ; } 
     set { _HQ = value; } 
    } 
} 

    protected void btn_Click(object sender, EventArgs e) 
    { 
     DataTable dt = new DataTable(); 
     dt.Columns.Add("Name",typeof(string)); 
     dt.Columns.Add("HQ", typeof(bool)); 

     DataRow dr = null; 
     dr = dt.NewRow(); 
     dr["Name"]="Arijit"; 
     dr["HQ"]=true; 
     dt.Rows.Add(dr); 

     dr = dt.NewRow(); 
     dr["Name"] = "Dibyendu"; 
     dr["HQ"] = false; 
     dt.Rows.Add(dr); 

     dr = dt.NewRow(); 
     dr["Name"] = "Tridip"; 
     dr["HQ"] = false; 
     dt.Rows.Add(dr); 


     List<Person> oPerson1 = (from c in dt.AsEnumerable() 
      select new Person 
      { 
       Name = c.Field<string>("Name"), 
       HQ = c.Field<bool>("HQ") 
      }).Skip(1).Take(2).ToList(); 


     List<Person> oPerson2 = (from c in dt.AsEnumerable() 
      select new Person 
      { 
       Name = c.Field<string>("Name"), 
       HQ = c.Field<bool>("HQ") 
      }).Take(1).Skip(2).ToList(); 

    } 

Trả lời

4

Hãy thử điều này mã.

Person oPerson1 = (from c in dt.AsEnumerable() 
select new Person 
{ 
    Name = c.Field<string>("Name"), 
    HQ = c.Field<bool>("HQ") 
}).First(); //first person in a list 


Person oPerson2 = (from c in dt.AsEnumerable() 
select new Person 
{ 
    Name = c.Field<string>("Name"), 
    HQ = c.Field<bool>("HQ") 
}).Skip(1).First(); //second person in a list 

However this code can be rewritten to be clearer: 

List<Person> persons = from c in dt.AsEnumerable() 
select new Person 
{ 
    Name = c.Field<string>("Name"), 
    HQ = c.Field<bool>("HQ") 
}; 

Person oPerson1 = persons[0]; 
Person oPerson2 = persons[1]; 
9

nếu bạn muốn đi ghi đầu tiên bạn có thể gọi những Take(1), First(), FirstOrDefault()

nếu bạn muốn lấy 1 kỷ lục trong các cuộc gọi giữa này: Skip(n).Take(1) nơi n - là số lượng hồ sơ bỏ qua

Khi bạn gọi Take(n) - không cần phải gọi Bỏ qua sau đó, nó đã chọn n bản ghi

+0

Sự khác biệt quan trọng. 'Take' trả về một' IEnumerable 'và' Đầu tiên' trả về 'TSource'. – Jess

1

Nếu bạn muốn nhận được chỉ có một hồ sơ, bạn nên thay thế thức gọi ToList với First() hoặc FirstOrDefault() họ đang ở đây chỉ dành riêng cho mục đích này. Sự khác biệt giữa hai phương pháp là, First() sẽ ném ngoại lệ nếu không có gì để trả về (ví dụ: bộ sưu tập trống). Và FirstOrDefault() sẽ trả lại default(T) (ví dụ: null cho các lớp và 0 cho các loại giá trị).

2

Tôi không chắc chắn ý của bạn là "lấy một và bỏ qua phần còn lại", nhưng tôi nghi ngờ bạn đang bối rối về cách hoạt động LINQ hoạt động. Chúng trả về một chuỗi mới dựa trên tiêu chí bạn đã chỉ định và chuỗi mới đó chỉ có chính xác những gì bạn đã yêu cầu.

Ví dụ: nếu bạn có Danh sách có ba mục và bạn gọi là Take(1), bạn sẽ lấy lại một IEnumerable với 1 mục. Không còn gì để "bỏ qua" vì chỉ có một phần tử trong danh sách của bạn. Bảng dữ liệu gốc của bạn không thay đổi - chuỗi LINQ là không thay đổi.

Có vẻ như tất cả các bạn thực sự muốn làm là:

List<Person> oPerson2 = (from c in dt.AsEnumerable() 
     select new Person 
     { 
      Name = c.Field<string>("Name"), 
      HQ = c.Field<bool>("HQ") 
     }).Take(1).ToList(); 

Tất nhiên, đây là một hoạt động rất phổ biến trong LINQ vì vậy không khác, phần nào "rõ ràng" cách để làm điều đó:

Person oPerson2 = (from c in dt.AsEnumerable() 
     select new Person 
     { 
      Name = c.Field<string>("Name"), 
      HQ = c.Field<bool>("HQ") 
     }).First(); 
3

Tôi muốn sử dụng IQueryable thay vì List.

Dù sao bạn có thể sử dụng Queryable.Skip bỏ qua không có các yếu tố mà bạn cần

IQueryable<Person> oPerson2 = (from c in dt.AsEnumerable() 
      select new Person 
      { 
       Name = c.Field<string>("Name"), 
       HQ = c.Field<bool>("HQ") 
      }).Skip(2).Take(1); 

Ngoài ra, bạn sẽ tìm hiểu thêm về vấn đề này trong Return or Skip Elements in a Sequence (LINQ to SQL)

1

Breaking xuống chaining sau đó:

List<Person> oPerson2 = (from c in dt.AsEnumerable() 
    select new Person 
    { 
    Name = c.Field<string>("Name"), 
    HQ = c.Field<bool>("HQ") 
    }).Take(1).Skip(2).ToList(); 

trở thành:

var tmp0 = (from c in dt.AsEnumerable() 
    select new Person 
    { 
    Name = c.Field<string>("Name"), 
    HQ = c.Field<bool>("HQ") 
    }); 
var tmp1 = tmp0.Take(1); 
var tmp2 = tmp1.Skip(2); 
List<Person> oPerson2 = tmp2.ToList(); 

Điều này giúp bạn dễ dàng nhìn thấy lỗi hơn. tmp0 là một liệt kê sẽ trả về mọi hàng có thể khi liệt kê. tmp1 là một enumerable sẽ trả về chỉ 1 hàng đầu tiên trong tmp0 (hoặc ít hơn nếu không có đủ hàng).tmp2 là một enumerable sẽ bỏ qua 2 hàng đầu tiên trong tmp1 (hoặc ít hơn nếu không có đủ hàng) và sau đó trả về phần còn lại. Cuối cùng oPerson2 làm cho các số đếm này thực sự trả lại kết quả của chúng và lưu trữ nó trong một danh sách.

Từ điều này, rõ ràng sai lầm là .Skip(2) vì nó lấy một phần tử một phần tử và bỏ qua tối đa 2 và để phần còn lại, dẫn đến danh sách tối đa (1 - 2, 0) = 0 phần tử.

Rời khỏi Skip() và bạn nhận được những gì bạn muốn, vì "mất đến 1" đã đòi hỏi "bỏ qua phần còn lại".

Các vấn đề liên quan