首页 > 代码库 > linq之InnerJoin和LeftJoin以及封装动态查询条件版本

linq之InnerJoin和LeftJoin以及封装动态查询条件版本

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                         };
View Code

上面的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                         };
View Code

 这样我们就能像数据库那样在本地进行实现。

 

正当本小菜得意洋洋的千篇一律的使用着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         }
View Code

接着调用代码测试,如下

 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                     }
View Code

初步测试通过,汗,小菜只能实现封装到此部分,如果在多表联查只能进行重载扩展了。

另外调用此方法,

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         }
View Code