Linq的出现,使数据集的处理显得愈来愈简便。很多时候对于本地数据集的处理,脑海中的第一反应,即尝试使用Linq来实现。诸如DataTable的innerJoin以及leftJoin等操作,很多时候我们一接到类似的需求,立马便动手,诸如以下demo:
一、InnerJoin
1 var qMyMx = from mxDr in _dtJgTcDetail.Rows.Cast<DataRow>().Where(drMx => id.Equals(drMx["TCID"].ToString())) 2 join item in _dtCashItem.Rows.Cast<DataRow>() on mxDr["SFXMID"].ToString() equals item["ID"].ToString() 3 select new 4 { 5 SFXMID = mxDr["SFXMID"].ToString(), 6 TCID = mxDr["TCID"].ToString(), 7 MC = item["MC"].ToString(), 8 NUM = mxDr["NUM"].ToString(), 9 DW = item["DW"].ToString(), 10 GBBM = item["GBBM"].ToString(), 11 ID = mxDr["ID"].ToString() 12 };
上面的Demo便是一个典型的InnerJoin,通过_dtJgTcDetail的SFXMID列 同 _dtCashItem的ID列进行联查。我们就会感叹Linq让我们对数据源的筛选变的如此简单,但如果是联合主键的时候,我们又如何处理多条件的联查呢?接着一起看下面的Demo:
1 var qMyMx = from mxDr in _dtJgTcDetail.Rows.Cast<DataRow>().Where(drMx => id.Equals(drMx["TCID"].ToString())) 2 join item in _dtCashItem.Rows.Cast<DataRow>() on new { XMID = mxDr ["TCID"].ToString(), JGLB = mxDr["JGBM"].ToString()} equals new { XMID = item["TCID"].ToString(), JGLB = item["JGLBBM"].ToString() } 3 select new 4 { 5 SFXMID = mxDr["SFXMID"].ToString(), 6 TCID = mxDr["TCID"].ToString(), 7 MC = item["MC"].ToString(), 8 NUM = mxDr["NUM"].ToString(), 9 DW = item["DW"].ToString(), 10 GBBM = item["GBBM"].ToString(), 11 ID = mxDr["ID"].ToString() 12 };
这样我们就能像数据库那样在本地进行实现。
正当本小菜得意洋洋的千篇一律的使用着Linq,有一天,一个同事提出了这样的想法,如何封装一个动态的InnerJoin呢(能接收不同的联查条件)?这让本小菜一愣神,怎么才能实现动态查询条件的InnerJoin。正好最近小菜在学习咱们原子里大牛老赵的Expression系列,于是,我想既然是动态查询条件,能否把这部分抽出来交给开发者来动态实现呢?于是如果传入 Expression<Func<DataRow,DataRow,bool>> exp 类型的参数能否实现心中所想?立马尝试,如下Demo:
1 public static IEnumerable<dynamic> InnerJoin(DataTable fstDt, DataTable ScdDt, Expression<Func<DataRow,DataRow,bool>> exp) 2 { 3 try 4 { 5 var q = from dr1 in fstDt.Rows.Cast<DataRow>() 6 from dr2 in ScdDt.Rows.Cast<DataRow>() 7 where exp.Compile()(dr1, dr2) 8 select new { dr1, dr2 }; 9 10 return q == null ? null : q.ToList(); 11 } 12 catch { } 13 return null; 14 }
接着调用代码测试,如下
1 var qMyMx = ClsComUI.InnerJoin(_dtJgTcDetail.Rows.Cast<DataRow>().Where(drMx => id.Equals(drMx["TCID"].ToString())).CopyToDataTable(), 2 _frmFth._dtCashItem, 3 (mxDr, item) => mxDr["SFXMID"].ToString().Equals(item["ID"].ToString())); 4 5 if (qMyMx.Count() > 0) 6 { 7 (gridControl2.DataSource as DataTable).Rows.Clear(); 8 DataTable dtMxBind = gridControl2.DataSource as DataTable; 9 qMyMx.ToList().ForEach(myItem => 10 { 11 DataRow drItem = dtMxBind.NewRow(); 12 drItem["SFXMID"] = myItem.dr1["SFXMID"].ToString(); 13 drItem["TCID"] = myItem.dr1["TCID"].ToString(); 14 drItem["MC"] = myItem.dr2["MC"].ToString(); 15 drItem["NUM"] = myItem.dr1["NUM"].ToString(); 16 drItem["DW"] = myItem.dr2["DW"].ToString(); 17 drItem["GBBM"] = myItem.dr2["GBBM"].ToString(); 18 drItem["ID"] = myItem.dr1["ID"].ToString(); 19 20 dtMxBind.Rows.Add(drItem); 21 }); 22 23 //初始化明细的明细库缓存 24 DoQueryJgMxk_MX(dtMxBind); 25 gridView2_FocusedRowChanged(null, null); 26 } 27 else 28 { 29 (gridControl2.DataSource as DataTable).Rows.Clear(); 30 }
初步测试通过,汗,小菜只能实现封装到此部分,如果在多表联查只能进行重载扩展了。
另外调用此方法,
var qMyMx =
ClsComUI.InnerJoin(_dtJgTcDetail.Rows.Cast<DataRow>().Where(drMx =>
id.Equals(drMx["TCID"].ToString())).CopyToDataTable(),
_frmFth._dtCashItem,
(mxDr, item) => mxDr["SFXMID"].ToString().Equals(item["ID"].ToString()));
传入的变量为(mxDr, item)
而输出的时候
drItem["SFXMID"] = myItem.dr1["SFXMID"].ToString();
drItem["TCID"] = myItem.dr1["TCID"].ToString();
drItem["MC"] = myItem.dr2["MC"].ToString();
drItem["NUM"] = myItem.dr1["NUM"].ToString();
drItem["DW"] = myItem.dr2["DW"].ToString();
drItem["GBBM"] = myItem.dr2["GBBM"].ToString();
drItem["ID"] = myItem.dr1["ID"].ToString();
只能使用公共方法内部定义的输出dr1和dr2。
小菜一直困扰如何解决,望各位大神告知小菜如何解决....在此,先感谢了。LeftJoin版本差不太多,直接附上代码:
二、LeftJoin版本
1 public static IEnumerable<dynamic> LeftJoin(DataTable fstDt, DataTable ScdDt, Expression<Func<DataRow, DataRow, bool>> exp) 2 { 3 try 4 { 5 var q = from dr1 in fstDt.Rows.Cast<DataRow>() 6 from dr2 in ScdDt.Rows.Cast<DataRow>().Where(needRows => exp.Compile()(dr1, needRows)).DefaultIfEmpty() 7 select new { dr1, dr2 }; 8 9 return q == null ? null : q.ToList(); 10 } 11 catch { } 12 return null; 13 14 //var qRstXm = ClsComUI.LeftJoin(q.Where(drFil => drFil["TCBZ"].ToString().Equals("0")).CopyToDataTable(), 15 // _dtJgMxk, 16 // (drYz, drJg) => drYz["SFXMID"].ToString().Equals(drJg["XMID"].ToString()) && strJglb.Equals(drJg["JGLBBM"].ToString()) 17 // ); 18 19 //var qRstTc = ClsComUI.LeftJoin(q.Where(drFil => drFil["TCBZ"].ToString().Equals("1")).CopyToDataTable(), 20 // _dtJgMxk, 21 // (drYz, drJg) => drYz["TCID"].ToString().Equals(drJg["TCID"].ToString()) && strJglb.Equals(drJg["JGLBBM"].ToString()) 22 // ); 23 }
linq之InnerJoin和LeftJoin以及封装动态查询条件版本,布布扣,bubuko.com
linq之InnerJoin和LeftJoin以及封装动态查询条件版本
原文:http://www.cnblogs.com/jchl/p/3776286.html