1. 程式人生 > >linq中分組查詢而且獲取每個分組中的第一條記錄,數據用於分頁綁定

linq中分組查詢而且獲取每個分組中的第一條記錄,數據用於分頁綁定

upd 但是 static groupby 麻煩 asc xxx each request

LINQ分組取出第一條數據

Person1: Id=1, Name="Test1"

Person2: Id=1, Name="Test1"

Person3: Id=2, Name="Test2"

以上list如果直接使用distinct方法進行過濾,仍然返回3條數據,而需要的結果是2條數據。下面給出解這個問題的方法:

方法1: Distinct 方法中使用的相等比較器。這個比較器需要重寫Equals和GetHashCode方法,個人不推薦,感覺較麻煩,需要些多余的類,並且用起來還要實例化一個比較器,當然自己也可以寫一個泛型的比較器生成工廠用來專門生成比較器,但仍然覺得較麻煩。

MSDN給出的做法,具體參照:http://msdn.microsoft.com/zh-cn/library/bb338049.aspx

方法2:自己擴展一個DistinctBy。這個擴展方法還是很不錯的,用起來很簡潔,適合為框架添加的Distinct擴展方法。

public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)

{

HashSet<TKey> seenKeys = new HashSet<TKey>();

foreach (TSource element in source)

{

if (seenKeys.Add(keySelector(element)))

{

yield return element;

}

}

}

使用方法如下(針對ID,和Name進行Distinct):

var query = people.DistinctBy(p => new { p.Id, p.Name });

若僅僅針對ID進行distinct:

var query = people.DistinctBy(p => p.Id);

方法3:通過GroupBy分組後,並取出第一條數據。簡單易用,很方便。這是一種迂回策略,代碼理解起來沒有Distinct表意清晰,雖然實現了效果。

List<Person> distinctPeople = allPeople

.GroupBy(p => new {p.Id, p.Name} )

.Select(g => g.First())

.ToList();

//這個看起來很美好,但是綁定到gridview時則不顯示也不提示錯誤,采用下面的方法很可靠

ViewState["0964zt"] = "簡易報警"; //不顯示暫停

bool xswg = this.chk_xswg.Checked;//是否顯示完工

if (xswg)//顯示所有延期的記錄,按照ddid降序排列的1000條記錄

{

var cx_dd_bj = (from aa in sjklj.sc_ddxx

where aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)

orderby aa.ddid descending

select aa).Take(1000).GroupBy(bb => bb.ddid);

List<sc_ddxx> lst_jybq = new List<sc_ddxx>();

lst_jybq.Clear();

foreach(var kk in cx_dd_bj)

{

foreach(var gg in kk)

{

lst_jybq.Add(gg);//獲取了第一條記錄

break;

}

}

this.gv_scjh.DataSource = lst_jybq;

try

{

this.gv_scjh.PageIndex = 0;

}

catch(Exception err)

{

aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");

}

this.gv_scjh.DataBind();

}

else //不顯示完工的,即沒有完工的,就是【待定】

{

var cx_dd_bj = (from aa in sjklj.sc_ddxx

where aa.czzt == "待定" && aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)

orderby aa.ddid descending

select aa).Take(1000).GroupBy(bb => bb.ddid);

List<sc_ddxx> lst_jybq = new List<sc_ddxx>();

lst_jybq.Clear();

foreach (var kk in cx_dd_bj)

{

foreach (var gg in kk)

{

lst_jybq.Add(gg);//獲取了第一條記錄

break;

}

}

this.gv_scjh.DataSource = lst_jybq;

try

{

this.gv_scjh.PageIndex = 0;

}

catch (Exception err)

{

aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");

}

this.gv_scjh.DataBind();

}

Linq分組及排序,取前N條記錄

2016年05月18日 15:02:10

閱讀數:5199

Linq多字段分組排序並取前N條記錄時,一定要先分組再排序,不然取到的記錄是不規則的

代碼示例【按HotWord分組,並取sorNum倒序,取前15條記錄】

  1. [Route("api/XXX/getHotWord")]
  2. public HttpResponseMessage Post(WordModel model)
  3. {
  4. try
  5. {
  6. using (BZTEntities ctx = new BZTEntities())
  7. {
  8. var wflist = from u in ctx.T_HotWord
  9. where u.Type==model.type
  10. group u by new { HotWord = u.HotWord, sortNum = u.SortNum } into g
  11. select new { g.Key.HotWord, g.Key.sortNum };
  12. wflist = wflist.OrderByDescending(x => x.sortNum);
  13. var hotWord = wflist.ToList().Take(15).Select(a => a.HotWord).ToList();
  14. var Str = string.Join(",", hotWord);
  15. return Request.CreateResponse(HttpStatusCode.OK, new { errorCode = 1, hotWord = Str });
  16. }
  17. }
  18. catch (Exception ex)
  19. {
  20. Log.Error("獲取xxxxx失敗:" + ex.Message, ex);
  21. return Request.CreateResponse(HttpStatusCode.OK, new { errorCode = 2 });
  22. }
  23. }
  24. }

特別提醒:list對象綁定gridview時,如果用自帶的分頁事件綁定,則不能實現分頁,下面的代碼完美解決。

bool xswg = this.chk_xswg.Checked;//是否顯示完工

if (xswg)//顯示所有延期的記錄,按照ddid降序排列的1000條記錄

{

var cx_dd_bj = (from aa in sjklj.sc_ddxx

where aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)

orderby aa.ddid descending

select aa).Take(1000).GroupBy(bb => bb.ddid).OrderByDescending(cc => cc.Key)

.Select(dd => dd.FirstOrDefault());

this.gv_scjh.DataSource = cx_dd_bj;

this.gv_scjh.DataBind();

// FirstOrDefault()是解決意外錯誤的好方法,否則可能沒有數據顯示甚至沒有提示

/*

List<sc_ddxx> lst_jybq = new List<sc_ddxx>();

lst_jybq.Clear();

foreach(var kk in cx_dd_bj)

{

foreach(var gg in kk)

{

lst_jybq.Add(gg);//獲取了第一條記錄

break;

}

}

//用戶viewstate["datajybj"]記錄list數據

ViewState["datajybj"] = lst_jybq;

this.gv_scjh.DataSource = lst_jybq;

try

{

this.gv_scjh.PageIndex = 0;

}

catch(Exception err)

{

aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");

}

this.gv_scjh.DataBind();

*/

}

else //不顯示完工的,即沒有完工的,就是【待定】

{

var cx_dd_bj = (from aa in sjklj.sc_ddxx

where aa.czzt == "待定" && aa.yq.HasValue && aa.yq.Value > 0 && ((aa.zt.HasValue && aa.zt == false) || aa.zt.HasValue == false)

orderby aa.ddid descending

select aa).Take(1000).GroupBy(bb => bb.ddid).OrderByDescending(cc => cc.Key)

.Select(dd => dd.FirstOrDefault());

this.gv_scjh.DataSource = cx_dd_bj;

this.gv_scjh.DataBind();

return;

/*

List<sc_ddxx> lst_jybq = new List<sc_ddxx>();

lst_jybq.Clear();

foreach (var kk in cx_dd_bj)

{

foreach (var gg in kk)

{

lst_jybq.Add(gg);//獲取了第一條記錄

break;

}

}

//用戶viewstate["datajybj"]記錄list數據

ViewState["datajybj"] = lst_jybq;

this.gv_scjh.DataSource = lst_jybq;

try

{

this.gv_scjh.PageIndex = 0;

}

catch (Exception err)

{

aspnetajaxjavascript.Msg(this.UpdatePanel1, err.Message, "2", "3000");

}

this.gv_scjh.DataBind();

*/

}

linq中分組查詢而且獲取每個分組中的第一條記錄,數據用於分頁綁定