2011-11-11 69 views
5

我试图记录一条记录并跳过其他记录。我的代码不会抛出任何错误,但不会给出任何输出。这是我的代码。所以请看看并告诉我我的代码中有什么问题。LINQ如何记录一条记录并跳过其余记录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(); 

    } 

回答

4

试试这个码。

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

如果你想采取第一条记录,你可以调用这些Take(1)First(),如果你想利用1个记录在中间调用此FirstOrDefault()

Skip(n).Take(1)其中n - 是跳过的记录

当你调用Take(n) - 不需要调用后跳过,它已经选择了N个记录

+0

重要的区别。 'Take'返回'IEnumerable ','First'返回'TSource'。 – Jess

1

如果你想获得一个记录,则应更换最终ToList电话与First()FirstOrDefault()他们在这里只是为了这个目的。 两种方法的区别在于,如果没有任何内容返回(例如空集合),First()将引发异常。 FirstOrDefault()将返回default(T)(例如,类为null,值类型为0)。

2

我不确定你的意思是“采取一个,跳过其余的”,但我怀疑你混淆了LINQ操作的工作方式。他们根据您指定的标准返回一个新的序列,并且该新序列只与您要求的完全相同。

例如,如果您有一个包含三个项目的列表,并且您调用了Take(1),则会返回带有1个项目的IEnumerable。没有什么可以“跳过”,因为列表中只有一个元素。您的原始数据表保持不变 - LINQ序列是不可变的。

这听起来像你真正想要做的是:

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

当然,这是在LINQ一个非常常见的操作,还有另外一个,多少有点“更清晰”的方式做到这一点:

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

我主张使用IQueryable而不是List

反正你可以使用Queryable.Skip跳过没有元素的需要

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); 

你还会发现更多关于这Return or Skip Elements in a Sequence (LINQ to SQL)

1

打破了链接,那么:

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(); 

变成:

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(); 

这使得查看错误更容易。 tmp0是一个枚举,枚举时将返回每个可能的行。 tmp1是一个枚举,它将只返回tmp0中的第一行(如果没有足够的行,则返回更少)。tmp2是一个可跳过tmp1中前2行的枚举(如果没有足够的行,则跳过更少),然后返回其余行。最后,oPerson2使这些枚举实际返回结果并将其存储在列表中。

由此可知,错误是.Skip(2),因为它采用了单元素枚举和跳过2,剩下的部分,导致列表中的最大(1 - 2,0)= 0元素。

退出Skip(),你会得到你想要的,因为“最多1”已经需要“跳过休息”。

相关问题