创设基于Dapper的多寡访问层,数据开辟框架

By admin in 4858.com on 2019年4月15日

 

欢迎使用 PDF.NET 数据开垦框架
(Ver 4.0)

【原创】塑造基于Dapper的多寡访问层

 

  • 前言

4858.com,  闲来无事,花几天武术将事先项目里用到的一个数额访问层整理了出去。完结单个实体的增加和删除改查,可进行存储进度,可输出再次回到参数,查询结果集可依照实况再次来到DataTable、DataSet和强类型,同时协理差异品种数据库。最近成熟的O福睿斯M框架多不胜数,再写三个出去,并非想表达自个儿写的有多好,一来以为现存成熟的OOdysseyM框架并无法灵活适用于大型ERP项目,二来有感于工作多年有须求写下局地事物。固然有种重复造轮子的感觉,但相信朋友们和本人同样,享受造轮子的经过并把它正是1种乐趣,对吧。

  • 调用示例

  1、LinQ 语法查询

4858.com 1

1     //LinQ 语法查询
2     query = rptBase.Query<Bas_Company>();
3     query = rptBase.Query<Bas_Company>(x => true);
4     query = rptBase.Query<Bas_Company>(x => true && (x.CompanyID ?? null) != null && new[] { "1", "2" }.Contains(x.CompanyID) &&
5         x.CompanyID.Substring(2, 5).TrimEnd() == "OK" && x.AllowUsed);

  二、分页查询

4858.com 2

1     //分页查询
2     query = rptBase.Query<Bas_Company>(new PageInfo(3, 20));
3     query = rptBase.Query<Bas_Company>(new PageInfo(3, 20), x => x.CompanyID == "FT");

  三、自定义脚本查询

4858.com 3

1     d = new DynamicParameters();
2     d.Add("CompanyName", "美之源科技有限公司", DbType.String, null, 20);
3     query = rptBase.Query<Bas_Company>("Select * From Bas_Company WHERE CompanyName = @CompanyName", d);

  四、自定义参数查询

4858.com 4

1     //自定义参数查询
2     d = new DynamicParameters();
3     d.Add("CompanyName", "美之源科技有限公司");
4     query = rptBase.Query<Bas_Company>("selectByName", null, d);

  5、带重回值查询

4858.com 5

1     //带返回值查询
2     d = new DynamicParameters();
3     d.Add("Row", null);
4     table = rptBase.QueryDataTable<Bas_Company>("returnValue", x => x.CompanyID != "FT", d);
5     eff = d.Get<int?>("Row");

  六、自定义实体查询

4858.com 6

1     //查询自定义实体
2     var query1 = rptBase.Query<ThinEntity>(typeof(Bas_Company).FullName, "thinEntity", "And CompanyID <> 'FT' ");

  7、DataTable 查询

4858.com 7

1     DataTable table = null;
2     table = rptBase.QueryDataTable<Bas_Company>();
3     table = rptBase.QueryDataTable<Bas_Company>(x => true);

  8、DataSet 查询

4858.com 8

1     DataSet data = null;
2     data = rptBase.QueryDataSet<Bas_Company>("Select",x => true);

  9、增删改

4858.com 9

4858.com 10

 1     //新增
 2     Bas_Company company = new Bas_Company();
 3     company.CompanyID = "TH";
 4     company.CompanyCode = "TH001";
 5     rptBase.Insert(company);
 6 
 7     //修改
 8     company.CompanyCode = "TH00x";
 9     rptBase.Update(company);
10     //批量修改
11     rptBase.Update<Bas_Company>(x => new Bas_Company { CompanyCode = "TH003" }, x => x.CompanyID == "TH");
12 
13     //删除
14     rptBase.Delete(company);

4858.com 11

  10、解析成字符串

4858.com 12

1     sql = rptBase.Resolve<Bas_Company>("Select",x => true && (x.CompanyID ?? null) != null && new[] { "1", "2" }.Contains(x.CompanyID) &&
2         x.CompanyID.Substring(2, 5).TrimEnd() == "OK" && x.AllowUsed);
3     sqlList.Add(sql);

  还有其余的重载那里就不一壹列举,源代码的单元测试里有很详细的申明。

  • 详尽分析

  先来探望项目架构截图:

4858.com 13

03.Src:第三方开源组件源码,有的近来并未有使用,先收藏着;
0四.Infrastructure:整个项目公用类库,包括部分Helper和公用类;
05.DataAccess:数据访问基本类库,实现Lambda表达式解析、Dapper封装等;
0六.Model:实体层,实体使用CodeSmith生成,包蕴实体和本子映射八个部分;
0九.Presentation:显示层,近期唯有二个单元测试项目。

  Dapper,多少个基于IDbConnection扩充的一点壹滴开源的轻、小、快的O安德拉M框架(项目源码  )。在本框架中,供给消除的首要性难题有如下几点:

  1. 怎么生成Dapper查询所要求的TSQL脚本和参数
  2. 何以将Lambda表明式解析成查询条件
  3. 如何将Dapper返回的IDataReader转化成DataTable和DataSet
  4. 什么样缓解大多数据库的主题素材

 

有关框架的名字由来

         在小编设计www.pwmis.cn
站点(原域名早已过期,未来正准备使用新域名
)的时候,考虑到架构的包容性和未来进级的大概,最珍视的是绝非丰富的流年去为网址增添和保证广大错综复杂的主次,所以在借鉴前人成功经验的功底上,设计了
壹套全新的敏捷数据处理框架 PWMIS Data development
Framework,简称PDF。本套框架的盘算是借鉴Java平台的Hibernate 和 iBatis
而来,兼有OPRADOM和SQL-MAP的性状,同时还参考了后来.NET的LINQ(本框架成型于200陆年,当时还未据书上说过LINQ)使用风格,设计了
OQL查询表达式。本框架的规划思想是通用的,完全能够移植到Java
平台,今后只提供了.NET平台的兑现,一时将本框架命令为

PDF.NET

(下载

————————————— 华丽丽的分割线

  一. 怎么着生成Dapper查询所急需的SQL语句和参数

  基于SQL和代码分离原则,数据库中每一张表都有三个POCO实体与之对应同时用两个Xml文件来讲述,包蕴表名称、字段、主键和增删改查SQL及参数。因为Xml文件的结构都是同样的,作者那边用CodeSmithStudio来自动生成。CodeSmith的语法跟Asp.Net的语法类似,那里  有相比较健全的求学财富,本文不做过多着墨。其余若有自定义SQL必要,则须要把自定义Xml文件放到别的目录,避防被CodeSmith覆盖。Xml文件结构如下:

4858.com 14

  1 <?xml version="1.0" encoding="utf-8" ?>
  2 <EntityMapper  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  3     <TableType>
  4         <TableName>Bas_Bank</TableName>
  5         <TypeFullName>XFramework.Model.Bas_Bank</TypeFullName>
  6     </TableType>
  7     <Properties>
  8         <Property>
  9             <Name>CompanyID</Name>
 10             <DbType>AnsiString</DbType>
 11             <NativeType>varchar</NativeType>
 12             <Precision>0</Precision>
 13             <Scale>0</Scale>
 14             <Size>10</Size>
 15         </Property>
 16         <Property>
 17             <Name>BankID</Name>
 18             <DbType>AnsiString</DbType>
 19             <NativeType>varchar</NativeType>
 20             <Precision>0</Precision>
 21             <Scale>0</Scale>
 22             <Size>20</Size>
 23         </Property>
 24         <Property>
 25             <Name>BankCode</Name>
 26             <DbType>String</DbType>
 27             <NativeType>nvarchar</NativeType>
 28             <Precision>0</Precision>
 29             <Scale>0</Scale>
 30             <Size>20</Size>
 31         </Property>
 32         <Property>
 33             <Name>BankName</Name>
 34             <DbType>String</DbType>
 35             <NativeType>nvarchar</NativeType>
 36             <Precision>0</Precision>
 37             <Scale>0</Scale>
 38             <Size>40</Size>
 39         </Property>
 40         <Property>
 41             <Name>SWIFT</Name>
 42             <DbType>String</DbType>
 43             <NativeType>nvarchar</NativeType>
 44             <Precision>0</Precision>
 45             <Scale>0</Scale>
 46             <Size>20</Size>
 47         </Property>
 48         <Property>
 49             <Name>AreaID</Name>
 50             <DbType>AnsiString</DbType>
 51             <NativeType>varchar</NativeType>
 52             <Precision>0</Precision>
 53             <Scale>0</Scale>
 54             <Size>19</Size>
 55         </Property>
 56         <Property>
 57             <Name>Address</Name>
 58             <DbType>String</DbType>
 59             <NativeType>nvarchar</NativeType>
 60             <Precision>0</Precision>
 61             <Scale>0</Scale>
 62             <Size>100</Size>
 63         </Property>
 64         <Property>
 65             <Name>Phone</Name>
 66             <DbType>AnsiString</DbType>
 67             <NativeType>varchar</NativeType>
 68             <Precision>0</Precision>
 69             <Scale>0</Scale>
 70             <Size>60</Size>
 71         </Property>
 72         <Property>
 73             <Name>ParentID</Name>
 74             <DbType>AnsiString</DbType>
 75             <NativeType>varchar</NativeType>
 76             <Precision>0</Precision>
 77             <Scale>0</Scale>
 78             <Size>20</Size>
 79         </Property>
 80         <Property>
 81             <Name>Level</Name>
 82             <DbType>Int32</DbType>
 83             <NativeType>int</NativeType>
 84             <Precision>10</Precision>
 85             <Scale>0</Scale>
 86             <Size>4</Size>
 87         </Property>
 88         <Property>
 89             <Name>IsDetail</Name>
 90             <DbType>Boolean</DbType>
 91             <NativeType>bit</NativeType>
 92             <Precision>1</Precision>
 93             <Scale>0</Scale>
 94             <Size>1</Size>
 95         </Property>
 96         <Property>
 97             <Name>FullName</Name>
 98             <DbType>String</DbType>
 99             <NativeType>nvarchar</NativeType>
100             <Precision>0</Precision>
101             <Scale>0</Scale>
102             <Size>100</Size>
103         </Property>
104         <Property>
105             <Name>FullParentID</Name>
106             <DbType>String</DbType>
107             <NativeType>nvarchar</NativeType>
108             <Precision>0</Precision>
109             <Scale>0</Scale>
110             <Size>80</Size>
111         </Property>
112         <Property>
113             <Name>ModifyDTM</Name>
114             <DbType>DateTime</DbType>
115             <NativeType>datetime</NativeType>
116             <Precision>23</Precision>
117             <Scale>3</Scale>
118             <Size>8</Size>
119         </Property>
120         <Property>
121             <Name>Remark</Name>
122             <DbType>String</DbType>
123             <NativeType>nvarchar</NativeType>
124             <Precision>0</Precision>
125             <Scale>0</Scale>
126             <Size>200</Size>
127         </Property>
128         <Property>
129             <Name>AllowUsed</Name>
130             <DbType>Boolean</DbType>
131             <NativeType>bit</NativeType>
132             <Precision>1</Precision>
133             <Scale>0</Scale>
134             <Size>1</Size>
135         </Property>
136     </Properties>
137     <Keys>
138         <Property>
139             <Name>CompanyID</Name>
140             <DbType>AnsiString</DbType>
141             <NativeType>varchar</NativeType>
142             <Precision>0</Precision>
143             <Scale>0</Scale>
144             <Size>10</Size>
145         </Property>
146         <Property>
147             <Name>BankID</Name>
148             <DbType>AnsiString</DbType>
149             <NativeType>varchar</NativeType>
150             <Precision>0</Precision>
151             <Scale>0</Scale>
152             <Size>20</Size>
153         </Property>
154     </Keys>
155     <Commands>
156         <Command>
157             <Key>Select</Key>
158             <CommandType>Text</CommandType>
159             <Text>
160              SELECT 
161             [CompanyID],
162             [BankID],
163             [BankCode],
164             [BankName],
165             [SWIFT],
166             [AreaID],
167             [Address],
168             [Phone],
169             [ParentID],
170             [Level],
171             [IsDetail],
172             [FullName],
173             [FullParentID],
174             [ModifyDTM],
175             [Remark],
176             [AllowUsed]
177             FROM [Bas_Bank]
178             WHERE 1=1 #WHERE#
179             </Text>
180         </Command>
181         <Command>
182             <Key>SelectByPaging</Key>
183             <CommandType>Text</CommandType>
184             <Text>
185             SELECT
186                 [CompanyID],
187                 [BankID],
188                 [BankCode],
189                 [BankName],
190                 [SWIFT],
191                 [AreaID],
192                 [Address],
193                 [Phone],
194                 [ParentID],
195                 [Level],
196                 [IsDetail],
197                 [FullName],
198                 [FullParentID],
199                 [ModifyDTM],
200                 [Remark],
201                 [AllowUsed],
202                 [XRecordCount],
203                 [XRowNum]
204             FROM(
205                 SELECT 
206                     [CompanyID],
207                     [BankID],
208                     [BankCode],
209                     [BankName],
210                     [SWIFT],
211                     [AreaID],
212                     [Address],
213                     [Phone],
214                     [ParentID],
215                     [Level],
216                     [IsDetail],
217                     [FullName],
218                     [FullParentID],
219                     [ModifyDTM],
220                     [Remark],
221                     [AllowUsed],
222                     Count(*) Over() as [XRecordCount],
223                     Row_Number() Over(Order By [CompanyID],[BankID],[BankCode],[BankName],[SWIFT],[AreaID],[Address],[Phone],[ParentID],[Level],[IsDetail],[FullName],[FullParentID],[ModifyDTM],[Remark],[AllowUsed]) as [XRowNum]
224                 FROM [Bas_Bank]
225                 WHERE 1=1 #WHERE#
226             ) a WHERE [XRowNum] BETWEEN #BETWEEN#
227             </Text>
228         </Command>
229         <Command>
230             <Key>SelectByKey</Key>
231             <CommandType>Text</CommandType>
232             <Text>
233              SELECT 
234             [CompanyID],
235             [BankID],
236             [BankCode],
237             [BankName],
238             [SWIFT],
239             [AreaID],
240             [Address],
241             [Phone],
242             [ParentID],
243             [Level],
244             [IsDetail],
245             [FullName],
246             [FullParentID],
247             [ModifyDTM],
248             [Remark],
249             [AllowUsed]
250             FROM [Bas_Bank]
251             WHERE 1=1         
252             And [CompanyID]=@CompanyID
253             And [BankID]=@BankID
254             </Text>
255             <Parameters>            
256                 <Parameter>
257                     <Name>CompanyID</Name>
258                     <DbType>AnsiString</DbType>
259                     <NativeType>varchar</NativeType>
260                     <Precision>0</Precision>
261                     <Scale>0</Scale>
262                     <Size>10</Size>
263                 </Parameter>
264                 <Parameter>
265                     <Name>BankID</Name>
266                     <DbType>AnsiString</DbType>
267                     <NativeType>varchar</NativeType>
268                     <Precision>0</Precision>
269                     <Scale>0</Scale>
270                     <Size>20</Size>
271                 </Parameter>
272             </Parameters>
273         </Command>
274         <Command>
275             <Key>Update</Key>
276             <CommandType>Text</CommandType>
277             <Text>
278             UPDATE [Bas_Bank] SET
279                     [BankCode] = @BankCode,
280                     [BankName] = @BankName,
281                     [SWIFT] = @SWIFT,
282                     [AreaID] = @AreaID,
283                     [Address] = @Address,
284                     [Phone] = @Phone,
285                     [ParentID] = @ParentID,
286                     [Level] = @Level,
287                     [IsDetail] = @IsDetail,
288                     [FullName] = @FullName,
289                     [FullParentID] = @FullParentID,
290                     [ModifyDTM] = @ModifyDTM,
291                     [Remark] = @Remark,
292                     [AllowUsed] = @AllowUsed
293             WHERE 1=1  #WHERE#
294             </Text>
295             <Parameters>
296                 <Parameter>
297                     <Name>BankCode</Name>
298                     <DbType>String</DbType>
299                     <NativeType>nvarchar</NativeType>
300                     <Precision>0</Precision>
301                     <Scale>0</Scale>
302                     <Size>20</Size>
303                 </Parameter>
304                 <Parameter>
305                     <Name>BankName</Name>
306                     <DbType>String</DbType>
307                     <NativeType>nvarchar</NativeType>
308                     <Precision>0</Precision>
309                     <Scale>0</Scale>
310                     <Size>40</Size>
311                 </Parameter>
312                 <Parameter>
313                     <Name>SWIFT</Name>
314                     <DbType>String</DbType>
315                     <NativeType>nvarchar</NativeType>
316                     <Precision>0</Precision>
317                     <Scale>0</Scale>
318                     <Size>20</Size>
319                 </Parameter>
320                 <Parameter>
321                     <Name>AreaID</Name>
322                     <DbType>AnsiString</DbType>
323                     <NativeType>varchar</NativeType>
324                     <Precision>0</Precision>
325                     <Scale>0</Scale>
326                     <Size>19</Size>
327                 </Parameter>
328                 <Parameter>
329                     <Name>Address</Name>
330                     <DbType>String</DbType>
331                     <NativeType>nvarchar</NativeType>
332                     <Precision>0</Precision>
333                     <Scale>0</Scale>
334                     <Size>100</Size>
335                 </Parameter>
336                 <Parameter>
337                     <Name>Phone</Name>
338                     <DbType>AnsiString</DbType>
339                     <NativeType>varchar</NativeType>
340                     <Precision>0</Precision>
341                     <Scale>0</Scale>
342                     <Size>60</Size>
343                 </Parameter>
344                 <Parameter>
345                     <Name>ParentID</Name>
346                     <DbType>AnsiString</DbType>
347                     <NativeType>varchar</NativeType>
348                     <Precision>0</Precision>
349                     <Scale>0</Scale>
350                     <Size>20</Size>
351                 </Parameter>
352                 <Parameter>
353                     <Name>Level</Name>
354                     <DbType>Int32</DbType>
355                     <NativeType>int</NativeType>
356                     <Precision>10</Precision>
357                     <Scale>0</Scale>
358                     <Size>4</Size>
359                 </Parameter>
360                 <Parameter>
361                     <Name>IsDetail</Name>
362                     <DbType>Boolean</DbType>
363                     <NativeType>bit</NativeType>
364                     <Precision>1</Precision>
365                     <Scale>0</Scale>
366                     <Size>1</Size>
367                 </Parameter>
368                 <Parameter>
369                     <Name>FullName</Name>
370                     <DbType>String</DbType>
371                     <NativeType>nvarchar</NativeType>
372                     <Precision>0</Precision>
373                     <Scale>0</Scale>
374                     <Size>100</Size>
375                 </Parameter>
376                 <Parameter>
377                     <Name>FullParentID</Name>
378                     <DbType>String</DbType>
379                     <NativeType>nvarchar</NativeType>
380                     <Precision>0</Precision>
381                     <Scale>0</Scale>
382                     <Size>80</Size>
383                 </Parameter>
384                 <Parameter>
385                     <Name>ModifyDTM</Name>
386                     <DbType>DateTime</DbType>
387                     <NativeType>datetime</NativeType>
388                     <Precision>23</Precision>
389                     <Scale>3</Scale>
390                     <Size>8</Size>
391                 </Parameter>
392                 <Parameter>
393                     <Name>Remark</Name>
394                     <DbType>String</DbType>
395                     <NativeType>nvarchar</NativeType>
396                     <Precision>0</Precision>
397                     <Scale>0</Scale>
398                     <Size>200</Size>
399                 </Parameter>
400                 <Parameter>
401                     <Name>AllowUsed</Name>
402                     <DbType>Boolean</DbType>
403                     <NativeType>bit</NativeType>
404                     <Precision>1</Precision>
405                     <Scale>0</Scale>
406                     <Size>1</Size>
407                 </Parameter>
408             </Parameters>
409         </Command>
410         <Command>
411             <Key>UpdateByKey</Key>
412             <CommandType>Text</CommandType>
413             <Text>
414             UPDATE [Bas_Bank] SET
415                     [BankCode] = @BankCode,
416                     [BankName] = @BankName,
417                     [SWIFT] = @SWIFT,
418                     [AreaID] = @AreaID,
419                     [Address] = @Address,
420                     [Phone] = @Phone,
421                     [ParentID] = @ParentID,
422                     [Level] = @Level,
423                     [IsDetail] = @IsDetail,
424                     [FullName] = @FullName,
425                     [FullParentID] = @FullParentID,
426                     [ModifyDTM] = @ModifyDTM,
427                     [Remark] = @Remark,
428                     [AllowUsed] = @AllowUsed
429             WHERE 1=1         
430             And [CompanyID]=@CompanyID 
431             And [BankID]=@BankID 
432             </Text>
433             <Parameters>
434                 <Parameter>
435                     <Name>BankCode</Name>
436                     <DbType>String</DbType>
437                     <NativeType>nvarchar</NativeType>
438                     <Precision>0</Precision>
439                     <Scale>0</Scale>
440                     <Size>20</Size>
441                 </Parameter>
442                 <Parameter>
443                     <Name>BankName</Name>
444                     <DbType>String</DbType>
445                     <NativeType>nvarchar</NativeType>
446                     <Precision>0</Precision>
447                     <Scale>0</Scale>
448                     <Size>40</Size>
449                 </Parameter>
450                 <Parameter>
451                     <Name>SWIFT</Name>
452                     <DbType>String</DbType>
453                     <NativeType>nvarchar</NativeType>
454                     <Precision>0</Precision>
455                     <Scale>0</Scale>
456                     <Size>20</Size>
457                 </Parameter>
458                 <Parameter>
459                     <Name>AreaID</Name>
460                     <DbType>AnsiString</DbType>
461                     <NativeType>varchar</NativeType>
462                     <Precision>0</Precision>
463                     <Scale>0</Scale>
464                     <Size>19</Size>
465                 </Parameter>
466                 <Parameter>
467                     <Name>Address</Name>
468                     <DbType>String</DbType>
469                     <NativeType>nvarchar</NativeType>
470                     <Precision>0</Precision>
471                     <Scale>0</Scale>
472                     <Size>100</Size>
473                 </Parameter>
474                 <Parameter>
475                     <Name>Phone</Name>
476                     <DbType>AnsiString</DbType>
477                     <NativeType>varchar</NativeType>
478                     <Precision>0</Precision>
479                     <Scale>0</Scale>
480                     <Size>60</Size>
481                 </Parameter>
482                 <Parameter>
483                     <Name>ParentID</Name>
484                     <DbType>AnsiString</DbType>
485                     <NativeType>varchar</NativeType>
486                     <Precision>0</Precision>
487                     <Scale>0</Scale>
488                     <Size>20</Size>
489                 </Parameter>
490                 <Parameter>
491                     <Name>Level</Name>
492                     <DbType>Int32</DbType>
493                     <NativeType>int</NativeType>
494                     <Precision>10</Precision>
495                     <Scale>0</Scale>
496                     <Size>4</Size>
497                 </Parameter>
498                 <Parameter>
499                     <Name>IsDetail</Name>
500                     <DbType>Boolean</DbType>
501                     <NativeType>bit</NativeType>
502                     <Precision>1</Precision>
503                     <Scale>0</Scale>
504                     <Size>1</Size>
505                 </Parameter>
506                 <Parameter>
507                     <Name>FullName</Name>
508                     <DbType>String</DbType>
509                     <NativeType>nvarchar</NativeType>
510                     <Precision>0</Precision>
511                     <Scale>0</Scale>
512                     <Size>100</Size>
513                 </Parameter>
514                 <Parameter>
515                     <Name>FullParentID</Name>
516                     <DbType>String</DbType>
517                     <NativeType>nvarchar</NativeType>
518                     <Precision>0</Precision>
519                     <Scale>0</Scale>
520                     <Size>80</Size>
521                 </Parameter>
522                 <Parameter>
523                     <Name>ModifyDTM</Name>
524                     <DbType>DateTime</DbType>
525                     <NativeType>datetime</NativeType>
526                     <Precision>23</Precision>
527                     <Scale>3</Scale>
528                     <Size>8</Size>
529                 </Parameter>
530                 <Parameter>
531                     <Name>Remark</Name>
532                     <DbType>String</DbType>
533                     <NativeType>nvarchar</NativeType>
534                     <Precision>0</Precision>
535                     <Scale>0</Scale>
536                     <Size>200</Size>
537                 </Parameter>
538                 <Parameter>
539                     <Name>AllowUsed</Name>
540                     <DbType>Boolean</DbType>
541                     <NativeType>bit</NativeType>
542                     <Precision>1</Precision>
543                     <Scale>0</Scale>
544                     <Size>1</Size>
545                 </Parameter>
546                 <Parameter>
547                     <Name>CompanyID</Name>
548                     <DbType>AnsiString</DbType>
549                     <NativeType>varchar</NativeType>
550                     <Precision>0</Precision>
551                     <Scale>0</Scale>
552                     <Size>10</Size>
553                 </Parameter>
554                 <Parameter>
555                     <Name>BankID</Name>
556                     <DbType>AnsiString</DbType>
557                     <NativeType>varchar</NativeType>
558                     <Precision>0</Precision>
559                     <Scale>0</Scale>
560                     <Size>20</Size>
561                 </Parameter>
562             </Parameters>
563         </Command>
564         <Command>
565             <Key>UpdateByExpr</Key>
566             <CommandType>Text</CommandType>
567             <Text>
568             UPDATE [Bas_Bank] SET
569             #SET#
570             WHERE 1=1  #WHERE#
571             </Text>
572         </Command>
573         <Command>
574             <Key>Insert</Key>
575             <CommandType>Text</CommandType>
576             <Text>            
577             INSERT INTO [Bas_Bank](
578                     [CompanyID],
579                     [BankID],
580                     [BankCode],
581                     [BankName],
582                     [SWIFT],
583                     [AreaID],
584                     [Address],
585                     [Phone],
586                     [ParentID],
587                     [Level],
588                     [IsDetail],
589                     [FullName],
590                     [FullParentID],
591                     [ModifyDTM],
592                     [Remark],
593                     [AllowUsed]
594             ) VALUES(
595                     @CompanyID,
596                     @BankID,
597                     @BankCode,
598                     @BankName,
599                     @SWIFT,
600                     @AreaID,
601                     @Address,
602                     @Phone,
603                     @ParentID,
604                     @Level,
605                     @IsDetail,
606                     @FullName,
607                     @FullParentID,
608                     @ModifyDTM,
609                     @Remark,
610                     @AllowUsed
611             )
612             
613             </Text>
614             <Parameters>
615                 <Parameter>
616                     <Name>CompanyID</Name>
617                     <DbType>AnsiString</DbType>
618                     <NativeType>varchar</NativeType>
619                     <Precision>0</Precision>
620                     <Scale>0</Scale>
621                     <Size>10</Size>
622                 </Parameter>
623                 <Parameter>
624                     <Name>BankID</Name>
625                     <DbType>AnsiString</DbType>
626                     <NativeType>varchar</NativeType>
627                     <Precision>0</Precision>
628                     <Scale>0</Scale>
629                     <Size>20</Size>
630                 </Parameter>
631                 <Parameter>
632                     <Name>BankCode</Name>
633                     <DbType>String</DbType>
634                     <NativeType>nvarchar</NativeType>
635                     <Precision>0</Precision>
636                     <Scale>0</Scale>
637                     <Size>20</Size>
638                 </Parameter>
639                 <Parameter>
640                     <Name>BankName</Name>
641                     <DbType>String</DbType>
642                     <NativeType>nvarchar</NativeType>
643                     <Precision>0</Precision>
644                     <Scale>0</Scale>
645                     <Size>40</Size>
646                 </Parameter>
647                 <Parameter>
648                     <Name>SWIFT</Name>
649                     <DbType>String</DbType>
650                     <NativeType>nvarchar</NativeType>
651                     <Precision>0</Precision>
652                     <Scale>0</Scale>
653                     <Size>20</Size>
654                 </Parameter>
655                 <Parameter>
656                     <Name>AreaID</Name>
657                     <DbType>AnsiString</DbType>
658                     <NativeType>varchar</NativeType>
659                     <Precision>0</Precision>
660                     <Scale>0</Scale>
661                     <Size>19</Size>
662                 </Parameter>
663                 <Parameter>
664                     <Name>Address</Name>
665                     <DbType>String</DbType>
666                     <NativeType>nvarchar</NativeType>
667                     <Precision>0</Precision>
668                     <Scale>0</Scale>
669                     <Size>100</Size>
670                 </Parameter>
671                 <Parameter>
672                     <Name>Phone</Name>
673                     <DbType>AnsiString</DbType>
674                     <NativeType>varchar</NativeType>
675                     <Precision>0</Precision>
676                     <Scale>0</Scale>
677                     <Size>60</Size>
678                 </Parameter>
679                 <Parameter>
680                     <Name>ParentID</Name>
681                     <DbType>AnsiString</DbType>
682                     <NativeType>varchar</NativeType>
683                     <Precision>0</Precision>
684                     <Scale>0</Scale>
685                     <Size>20</Size>
686                 </Parameter>
687                 <Parameter>
688                     <Name>Level</Name>
689                     <DbType>Int32</DbType>
690                     <NativeType>int</NativeType>
691                     <Precision>10</Precision>
692                     <Scale>0</Scale>
693                     <Size>4</Size>
694                 </Parameter>
695                 <Parameter>
696                     <Name>IsDetail</Name>
697                     <DbType>Boolean</DbType>
698                     <NativeType>bit</NativeType>
699                     <Precision>1</Precision>
700                     <Scale>0</Scale>
701                     <Size>1</Size>
702                 </Parameter>
703                 <Parameter>
704                     <Name>FullName</Name>
705                     <DbType>String</DbType>
706                     <NativeType>nvarchar</NativeType>
707                     <Precision>0</Precision>
708                     <Scale>0</Scale>
709                     <Size>100</Size>
710                 </Parameter>
711                 <Parameter>
712                     <Name>FullParentID</Name>
713                     <DbType>String</DbType>
714                     <NativeType>nvarchar</NativeType>
715                     <Precision>0</Precision>
716                     <Scale>0</Scale>
717                     <Size>80</Size>
718                 </Parameter>
719                 <Parameter>
720                     <Name>ModifyDTM</Name>
721                     <DbType>DateTime</DbType>
722                     <NativeType>datetime</NativeType>
723                     <Precision>23</Precision>
724                     <Scale>3</Scale>
725                     <Size>8</Size>
726                 </Parameter>
727                 <Parameter>
728                     <Name>Remark</Name>
729                     <DbType>String</DbType>
730                     <NativeType>nvarchar</NativeType>
731                     <Precision>0</Precision>
732                     <Scale>0</Scale>
733                     <Size>200</Size>
734                 </Parameter>
735                 <Parameter>
736                     <Name>AllowUsed</Name>
737                     <DbType>Boolean</DbType>
738                     <NativeType>bit</NativeType>
739                     <Precision>1</Precision>
740                     <Scale>0</Scale>
741                     <Size>1</Size>
742                 </Parameter>
743             </Parameters>
744         </Command>
745         <Command>
746             <Key>Delete</Key>
747             <CommandType>Text</CommandType>
748             <Text>
749             DELETE FROM [Bas_Bank]
750             WHERE 1=1  #WHERE#
751             </Text>
752         </Command>
753         <Command>
754             <Key>DeleteByKey</Key>
755             <CommandType>Text</CommandType>
756             <Text>
757             DELETE FROM [Bas_Bank]
758             WHERE 1=1 
759             And [CompanyID]=@CompanyID 
760             And [BankID]=@BankID 
761             </Text>
762             <Parameters>        
763                 <Parameter>
764                     <Name>CompanyID</Name>
765                     <DbType>AnsiString</DbType>
766                     <NativeType>varchar</NativeType>
767                     <Precision>0</Precision>
768                     <Scale>0</Scale>
769                     <Size>10</Size>
770                 </Parameter>
771                 <Parameter>
772                     <Name>BankID</Name>
773                     <DbType>AnsiString</DbType>
774                     <NativeType>varchar</NativeType>
775                     <Precision>0</Precision>
776                     <Scale>0</Scale>
777                     <Size>20</Size>
778                 </Parameter>
779             </Parameters>
780         </Command>
781     </Commands>
782 </EntityMapper>

4858.com 15

  注意看Command节点,可以总结明了为数据库命令(下称命令),相比根本的是Text和Parameters子节点。这一个命令有的带有参数有的则并未有,没带参数的会有1个
##
占位符。没带参数的命0000000令,其参数恐怕通过硬编码生成也有望因此解析拉姆da表达式生成,怎么样解析拉姆da表明式会在接下去的第2点介绍。带有参数的下令,其参数名跟字段名相同,依据实体实例与字段名称就能够明确参数的值。 

4858.com 16

 1     public Command Build<T>(string cmdName, T TEntity)
 2         where T : class
 3     {
 4         Command cmd = this.GetCommand(typeof(T), cmdName);
 5         foreach (Parameter parameter in cmd.Parameters)
 6         {
 7             //赋参数值
 8             object value = AccFacHelper.Get(TEntity, parameter.Name);
 9             parameter.Value = value;
10         }
11 
12         return cmd;
13     }

4858.com 17

  2. 什么样将拉姆da表明式解析成查询条件

  很早从前大拿老赵就写过壹篇博文 [恢宏LINQ to SQL:使用拉姆da
Expression批量删除数据],基本思路是达成八个Expression<Func<T,bool>>解析器并将拉姆da解析为末段须求施行的TSQL。不过老赵的实现并不完整,不能够分析像 f=>true
f=>!f.FieldName f=>string.Length
f=>string[].Contains(s) 等表明式。小编在她的底子上再扩张了拍卖,并且把规范和参数分开来以适应Dapper的参数供给,看代码片段:

4858.com 18

 1   case ExpressionType.Constant:
 2         //True常量解析成1==1 Flase常量解析成1==2
 3         bool value = Convert.ToBoolean(((ConstantExpression)expr).Value);
 4         leftExpr = Expression.Constant(1);
 5         rightExpr = Expression.Constant(value ? 1 : 2);
 6 
 7         break;
 8 
 9   ... ...
10 
11   string condition = b.NodeType == ExpressionType.Coalesce ? 
12         string.Format("({0}({1},{2}))", opr, left, right) : 
13         string.Format("({0} {1} {2})", left, opr, right);
14 
15   ......
16 
17   condition = string.Format(" AND {0}", _stcConditions.Pop());
18     MatchCollection matches = Regex.Matches(condition, string.Format(@"{0}(?<Name>p(?<Index>[0-9]+))", _parameterPrefix));
19     foreach (Match match in matches)
20     {
21         if (!match.Success) continue;
22 
23         string index = match.Groups["Index"].Value;
24         string parameterName = match.Groups["Name"].Value;
25         if (_parameters[parameterName] == null) _parameters.Add(parameterName, _lstArguments[Convert.ToInt32(index)]);
26     }

4858.com 19

   3. 如何将Dapper返回的IDataReader转化成DataTable和DataSet

   IDataReader转化成DataTable相对轻易,直接调用DataTable.Load(IDataReader)重载就足以,比较费心的是转成DataSet。DataSet.Load方法的七个重载都要传送DataTable[]形参,但在IDataReader填充DataSet以前我们是无力回天精通它包蕴某个许个数据集,也就不可能分明哪些给DataSet.Load传参,这就好像的确是个相互争持的命题。先别着急,想想以前日常用的SqlDataAdapter,它就有SqlDataAdapter.Fill(DataSet)重载。它能直接填充DataSet而不用传递DataTable[]形参,那么理论上来讲DataSet.Load方法也不必要传递才对,因为实在无论DataSet.Load依然SqlDataAdapter.Fill,它们中间唯有都以对IDataReader的层层封装而已。如此看来,只要弄清楚SqlDataAdapter.Fill(DataSet)重载,大家的主题材料便会一蹴而就了。

  祭出反编写翻译利器.NET
Reflector,先来看望SqlDataAdapter.Fill(DataSet)到底都干了些什么:  

4858.com 20

 1 public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
 2 {
 3     public override int Fill(DataSet dataSet)
 4     {
 5         try
 6         {
 7             IDbCommand selectCommand = this._IDbDataAdapter.SelectCommand;
 8             CommandBehavior fillCommandBehavior = this.FillCommandBehavior;
 9             num = this.Fill(dataSet, 0, 0, "Table", selectCommand, fillCommandBehavior);
10         }
11         finally
12         {
13             Bid.ScopeLeave(ref ptr);
14         }
15         return num;
16     }
17 }
18 
19 public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
20 {
21     protected virtual int Fill(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
22     {
23         try
24         {
25             //srcTable="Table",注意跟踪形参
26             num = this.FillInternal(dataSet, null, startRecord, maxRecords, srcTable, command, behavior);
27         }
28         finally
29         {
30             Bid.ScopeLeave(ref ptr);
31         }
32         return num;
33     }
34 }
35 
36 public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
37 {
38     private int FillInternal(DataSet dataset, DataTable[] datatables, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
39     {
40         bool flag = null == command.Connection;
41         try
42         {
43             try
44             {
45                 using (IDataReader reader = null)
46                 {
47                     reader = command.ExecuteReader(behavior);
48                     ... ...
49                     return this.Fill(dataset, srcTable, reader, startRecord, maxRecords);
50                 }
51             }
52             finally
53             {
54                 QuietClose(connection, open);
55             }
56         }
57         finally
58         {
59             if (flag)
60             {
61                 command.Transaction = null;
62                 command.Connection = null;
63             }
64         }
65         return 0;
66     }
67 }
68 
69 public class DataAdapter : Component, IDataAdapter
70 {
71     protected virtual int Fill(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
72     {
73         try
74         {            
75             DataReaderContainer container = DataReaderContainer.Create(dataReader, this.ReturnProviderSpecificTypes);
76             num = this.FillFromReader(dataSet, null, srcTable, container, startRecord, maxRecords, null, null);
77         }
78         finally
79         {
80             Bid.ScopeLeave(ref ptr);
81         }
82         return num;
83     }
84 }

4858.com 21

  看到了没,SqlDataAdapter.Fill(DataSet)方法内部是调用了此外2个重载,形参srcTable就是1个硬编码的”Table”。

  再来看看DataSet.Load的里边处理:

4858.com 22

 1 public class DataSet : MarshalByValueComponent, IListSource, IXmlSerializable, ISupportInitializeNotification, ISupportInitialize, ISerializable
 2 {
 3     public virtual void Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler, params DataTable[] tables)
 4     {        
 5         try
 6         {
 7             LoadAdapter adapter = new LoadAdapter {
 8                 FillLoadOption = loadOption,
 9                 MissingSchemaAction = MissingSchemaAction.AddWithKey
10             };
11             if (errorHandler != null)
12             {
13                 adapter.FillError += errorHandler;
14             }
15             adapter.FillFromReader(tables, reader, 0, 0);
16             ... ...
17         }
18         finally
19         {
20             ... ...
21         }
22     }
23 }
24 
25 internal sealed class LoadAdapter : DataAdapter
26 {
27     internal int FillFromReader(DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords)
28     {
29         return this.Fill(dataTables, dataReader, startRecord, maxRecords);
30     }
31 }
32 
33  

4858.com 23

   借使大家把LoadAdapter.FillFrom里德r方法修改四个,调用Load艾达pter.Fill的别的二个重载LoadAdapter.Fill(DataSet,string,IDataReader,int,int),而首个形参只需求传”Table”而已。最后完毕代码: 

4858.com 24

 1 /// <summary>
 2 /// 数据适配器,扩展Fill方法
 3 /// .NET的DataSet.Load方法,底层调用DataAdapter.Fill(DataTable[], IDataReader, int, int)
 4 /// Dapper想要返回DataSet,需要重写Load方法,不必传入DataTable[],因为数组长度不确定
 5 /// </summary>
 6 public class XLoadAdapter : DataAdapter
 7 {
 8     public XLoadAdapter()
 9     {
10     }
11 
12     public int FillFromReader(DataSet ds, IDataReader dataReader, int startRecord, int maxRecords)
13     {
14         return this.Fill(ds, "Table", dataReader, startRecord, maxRecords);
15     }
16 }
17 
18 /// <summary>
19 /// 扩展Load方法
20 /// </summary>
21 public class XDataSet : DataSet
22 {
23     public override void Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler handler, params DataTable[] tables)
24     {
25         XLoadAdapter adapter = new XLoadAdapter
26         {
27             FillLoadOption = loadOption,
28             MissingSchemaAction = MissingSchemaAction.AddWithKey
29         };
30         if (handler != null)
31         {
32             adapter.FillError += handler;
33         }
34         adapter.FillFromReader(this, reader, 0, 0);
35         if (!reader.IsClosed && !reader.NextResult())
36         {
37             reader.Close();
38         }
39     }
40 }
41 
42 //调用
43 IDataReader reader = _session.Connection.ExecuteReader(command, dynParameters,
44     _session.Transaction, _session.DataSource.CommandTimeout, commandType);
45 DataSet ds = new XDataSet();
46 ds.Load(reader, LoadOption.OverwriteChanges, null, new DataTable[] { });

4858.com 25

    4. 总结

   本框架在Dapper的底蕴上再做封装,辅助Lambda表明式树查询也支撑纯Sql查询,相对来讲比较灵活。但限于个人水平,未有把EmitMapper完美整合进来,只是简单的进展了引用,假设情侣们有好的建议,在下诚心请教。必要源码的恋人留个QQ邮箱笔者单独发啊,园子的附属类小部件最大10M导致源码上传不了。(已上传至百度云盘 )

 

 

分类: 数量访问

标签: Dapper, 多少访问

 

 

 

创设基于Dapper的多寡访问层,数据开辟框架。 

1. 概述

前言

框架协助的效劳

  • UI层(WinForm/Web)控件数据绑定、映射与查询;
  • BLL层实体对象查询(OQL)
  • DAL层SQL语句和.NET数据访问代码映射(查看
    SQL-MAP
    原理)

详见说来,框架还蕴藏以下特征成效:

  • 看似LINQ的支持O讴歌MDXM实体类查询的OQL表明式(有了LINQ为何还要搞一个OQL?本框架
    OQL的主导陈设在LINQ大概说本身知道
    LINQ在此之前,其余,.NET三.五框架才正式协助LINQ,而笔者辈公司的贰个出品却因为使用了三.5框架安装配备不便宜成为店四和客服平日怨声载道的说辞。
    未来还有如此的理由,大家热切须求二个看似LINQ的东西运营在好几客户过时的机器上。
  • 不用任何后台代码就能够分页的增加数据分页控件。
  • 只必要1行代码达成页面数据的增,删,改,查。
  • 依照SQL词法分析的支撑多种数据库的相当的慢分页类,你只供给设置SQL语句和分页属性它便可见为你转移特定数据库平台的当前页数据的SQL语句。
  • 一套实用工具,能够生成实体类和依照SQL配置文件自动生成代码的代码生成器以及SQL配置文件管理程序。
  • 越来越多的机能等待你去发现:)

【原创】重复造轮子之高仿EntityFramework

 

  • 前言

在上一篇《【原创】营造基于Dapper的数目访问层》中,Dapper在应付多表自由关联、分组查询、匿名查询等选拔场景时平常要手动写SQL语句。看着代码里满屏的革命SQL字符串,大致头大,于是便萌发重复造O锐界M这几个轮子的意念。本OHavalM在API设计上最大程度地借鉴
EF
的写法,协理链式查询(点标志)、查询表明式、聚合查询、分组排序、批量插入、批量更新、批量去除、一:一关联外键等。在实体绑定层面,使用
Emit 来动态构建绑定指令,质量最大限度地类似原生水平。

  • 性能

4858.com 26

 8000笔记录循环读1000次,同时加载一:一关乎的外键,速度比 EF 稍快。

  • 语法
  1. 单表查询

4858.com 27

// 查询表达式
var query = from a in context.GetTable<Inte_CRM.Demo>()
            select a;
var r1 = query.ToList();
// 点标记
query = context.GetTable<Inte_CRM.Demo>();
r1 = query.ToList();
//SQL=> 
//SELECT 
//t0.[DemoId] AS [DemoId],
//t0.[DemoCode] AS [DemoCode],
//t0.[DemoName] AS [DemoName],
//...
//t0.[DemoLong] AS [DemoLong],
//t0.[DemoLong_Nullable] AS [DemoLong_Nullable]
//FROM [Sys_Demo] t0

4858.com 28

  1. 论及查询

4858.com 29

// INNER JOIN
var query =
    from a in context.GetTable<Inte_CRM.CRM_SaleOrder>()
    join b in context.GetTable<Inte_CRM.Client>() on a.ClientId equals b.ClientId
    join c in context.GetTable<Inte_CRM.CloudServer>() on b.CloudServerId equals c.CloudServerId
    where a.ClientId > 0
    select a;
var r1 = query.ToList();
// 点标记
query = context
    .GetTable<Inte_CRM.CRM_SaleOrder>()
    .Join(context.GetTable<Inte_CRM.Client>(), a => a.ClientId, b => b.ClientId, (a, b) => new { Sale = a, Buyer = b })
    .Join(context.GetTable<Inte_CRM.CloudServer>(), b => b.Buyer.CloudServerId, c => c.CloudServerId, (a, c) => new Inte_CRM.CRM_SaleOrder { })
    .Where(a => a.ClientId > 0);
//r1 = query.ToList();
//SQL=>
//SELECT 
//t0.[OrderId] AS [OrderId],
//t0.[OrderNo] AS [OrderNo],
//t0.[Remark] AS [Remark],
//t0.[ClientId] AS [ClientId]
//FROM [CRM_SaleOrder] t0 
//INNER JOIN [Bas_Client] t1 ON t0.[ClientId] = t1.[ClientId]
//INNER JOIN [Sys_CloudServer] t2 ON t1.[CloudServerId] = t2.[CloudServerId]
//WHERE t0.[ClientId] > 0

4858.com 30

  1. 分组分页

4858.com 31

// 分组后再分页
query =
    from a in context.GetTable<Inte_CRM.Client>()
    where a.ClientName == "TAN"
    group a by new { a.ClientId, a.ClientName } into g
    where g.Key.ClientId > 0
    orderby new { g.Key.ClientName, g.Key.ClientId }
    select new
    {
        Id = g.Key.ClientId,
        Name = g.Min(a => a.ClientId)
    };
query = query.Skip(2).Take(3);
r1 = query.ToList();
//SQL=> 
//SELECT 
//t0.[Id],
//t0.[Name]
//FROM ( 
//    SELECT 
//    t0.[ClientId] AS [Id],
//    MIN(t0.[ClientId]) AS [Name],
//    t0.[ClientName] AS [ClientName]
//    FROM [Bas_Client] t0 
//    WHERE t0.[ClientName] = N'TAN'
//    GROUP BY t0.[ClientId],t0.[ClientName]
//    Having t0.[ClientId] > 0
// ) t0
//ORDER BY t0.[ClientName]
//OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY 

4858.com 32

  1. 批量计划

4858.com 33

context.Insert<Inte_CRM.Thin>(collection);
context.SubmitChanges();
//SQL=> 
//INSERT INTO[Sys_Thin]
//([ThinId],[ThinName])
//VALUES
//(2, N'002'),(3,N'003')

4858.com 34

  1. 导航属性

4858.com 35

// 更简单的赋值方式 
// 适用场景:在显示列表时只想显示外键表的一两个字段
query =
    from a in context.GetTable<Inte_CRM.CRM_SaleOrder>()
    select new Inte_CRM.CRM_SaleOrder(a)
    {
        Client = new Inte_CRM.Client(a.Client)
        {
            CloudServer = new Inte_CRM.CloudServer
            {
                CloudServerId = a.Client.CloudServer.CloudServerId,
                CloudServerName = a.Client.CloudServer.CloudServerName
            }
        },
        HeavyBuyer = new Inte_CRM.Client
        {
            ClientId = a.Client.ClientId + 10,
            ClientName = a.Client.ClientName + "_heavy",
            CloudServer = new Inte_CRM.CloudServer
            {
                CloudServerId = a.Client.CloudServer.CloudServerId + 10,
                CloudServerName = a.Client.CloudServer.CloudServerName + "_heavy",
            }
        }
    };
r1 = query.ToList();
//SQL=>
//SELECT 
//t0.[OrderId] AS [OrderId],
//t0.[OrderNo] AS [OrderNo],
//t0.[Remark] AS [Remark],
//t0.[ClientId] AS [ClientId],
//t1.[ClientId] AS [ClientId1],
//t1.[ClientCode] AS [ClientCode],
//t1.[ClientName] AS [ClientName],
//t1.[State] AS [State],
//t1.[ActiveDate] AS [ActiveDate],
//t1.[CloudServerId] AS [CloudServerId],
//t2.[CloudServerId] AS [CloudServerId1],
//t2.[CloudServerName] AS [CloudServerName],
//t1.[ClientId] + 10 AS [ClientId2],
//t1.[ClientName] + N'_heavy' AS [ClientName1],
//t2.[CloudServerId] + 10 AS [CloudServerId2],
//t2.[CloudServerName] + N'_heavy' AS [CloudServerName1]
//FROM [CRM_SaleOrder] t0 
//LEFT JOIN [Bas_Client] t1 ON t0.[ClientId] = t1.[ClientId]
//LEFT JOIN [Sys_CloudServer] t2 ON t1.[CloudServerId] = t2.[CloudServerId]

4858.com 36

 

此外越来越多示例在源码的 demo
中有详细表达,源码地址:

 

 

 

MyCAT 帮忙跨库表 Join,如今版本仅支持跨库两表
Join。即使那样,已经能够知足我们当先5/10的事体场景。况且,Join
过多的表恐怕带来的性格问题也是很劳苦的。

  入坑 wcdb
有四个月了,全部来讲依旧很不错的,具体优点能够参照文档表明,由于官方明显说明不扶助SQL 只能本身写八个恢弘帮助一下了 

与任何数据处理框架的涉及

       
本框架是计算种种多少处理框架的帮助和益处,去除其复杂后的轻量级的数量处理框,所以或者未有您熟知的下列重量级框架庞大的功用。本框架的设计指标是
轻量,飞快,通用,易学 !

  • Hibernate:借鉴了它的OKugaM原理和HQL语言,使用了就像的简要的O猎豹CS6M功用;
  • iBatis:借鉴了其SQL-MAP功效,对其复杂进行了全力精简;
  • LINQ/Entity Framework:提供类似LINQ的OQL语法

【原创】重复造轮子之高仿EntityFramework

 

  • 前言

在上一篇《【原创】塑造基于Dapper的数额访问层》中,Dapper在应付多表自由关联、分组查询、匿名查询等选用场景时平日要手动写SQL语句。望着代码里满屏的新民主主义革命SQL字符串,大约头大,于是便萌发重复造OHummerH二M那么些轮子的意念。本O昂科威M在API设计上最大程度地借鉴
EF
的写法,扶助链式查询(点标志)、查询表达式、聚合查询、分组排序、批量安顿、批量更新、批量删减、壹:1关乎外键等。在实体绑定层面,使用
Emit 来动态营造绑定指令,品质最大限度地接近原生水平。

  • 性能

4858.com 37

 7000笔记录循环读壹仟次,同时加载壹:一涉嫌的外键,速度比 EF 稍快。

  • 语法
  1. 单表查询

4858.com 38

// 查询表达式
var query = from a in context.GetTable<Inte_CRM.Demo>()
            select a;
var r1 = query.ToList();
// 点标记
query = context.GetTable<Inte_CRM.Demo>();
r1 = query.ToList();
//SQL=> 
//SELECT 
//t0.[DemoId] AS [DemoId],
//t0.[DemoCode] AS [DemoCode],
//t0.[DemoName] AS [DemoName],
//...
//t0.[DemoLong] AS [DemoLong],
//t0.[DemoLong_Nullable] AS [DemoLong_Nullable]
//FROM [Sys_Demo] t0

4858.com 39

  1. 涉嫌查询

4858.com 40

// INNER JOIN
var query =
    from a in context.GetTable<Inte_CRM.CRM_SaleOrder>()
    join b in context.GetTable<Inte_CRM.Client>() on a.ClientId equals b.ClientId
    join c in context.GetTable<Inte_CRM.CloudServer>() on b.CloudServerId equals c.CloudServerId
    where a.ClientId > 0
    select a;
var r1 = query.ToList();
// 点标记
query = context
    .GetTable<Inte_CRM.CRM_SaleOrder>()
    .Join(context.GetTable<Inte_CRM.Client>(), a => a.ClientId, b => b.ClientId, (a, b) => new { Sale = a, Buyer = b })
    .Join(context.GetTable<Inte_CRM.CloudServer>(), b => b.Buyer.CloudServerId, c => c.CloudServerId, (a, c) => new Inte_CRM.CRM_SaleOrder { })
    .Where(a => a.ClientId > 0);
//r1 = query.ToList();
//SQL=>
//SELECT 
//t0.[OrderId] AS [OrderId],
//t0.[OrderNo] AS [OrderNo],
//t0.[Remark] AS [Remark],
//t0.[ClientId] AS [ClientId]
//FROM [CRM_SaleOrder] t0 
//INNER JOIN [Bas_Client] t1 ON t0.[ClientId] = t1.[ClientId]
//INNER JOIN [Sys_CloudServer] t2 ON t1.[CloudServerId] = t2.[CloudServerId]
//WHERE t0.[ClientId] > 0

4858.com 41

  1. 分组分页

4858.com 42

// 分组后再分页
query =
    from a in context.GetTable<Inte_CRM.Client>()
    where a.ClientName == "TAN"
    group a by new { a.ClientId, a.ClientName } into g
    where g.Key.ClientId > 0
    orderby new { g.Key.ClientName, g.Key.ClientId }
    select new
    {
        Id = g.Key.ClientId,
        Name = g.Min(a => a.ClientId)
    };
query = query.Skip(2).Take(3);
r1 = query.ToList();
//SQL=> 
//SELECT 
//t0.[Id],
//t0.[Name]
//FROM ( 
//    SELECT 
//    t0.[ClientId] AS [Id],
//    MIN(t0.[ClientId]) AS [Name],
//    t0.[ClientName] AS [ClientName]
//    FROM [Bas_Client] t0 
//    WHERE t0.[ClientName] = N'TAN'
//    GROUP BY t0.[ClientId],t0.[ClientName]
//    Having t0.[ClientId] > 0
// ) t0
//ORDER BY t0.[ClientName]
//OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY 

4858.com 43

  1. 批量布置

4858.com 44

context.Insert<Inte_CRM.Thin>(collection);
context.SubmitChanges();
//SQL=> 
//INSERT INTO[Sys_Thin]
//([ThinId],[ThinName])
//VALUES
//(2, N'002'),(3,N'003')

4858.com 45

  1. 导航属性

4858.com 46

// 更简单的赋值方式 
// 适用场景:在显示列表时只想显示外键表的一两个字段
query =
    from a in context.GetTable<Inte_CRM.CRM_SaleOrder>()
    select new Inte_CRM.CRM_SaleOrder(a)
    {
        Client = new Inte_CRM.Client(a.Client)
        {
            CloudServer = new Inte_CRM.CloudServer
            {
                CloudServerId = a.Client.CloudServer.CloudServerId,
                CloudServerName = a.Client.CloudServer.CloudServerName
            }
        },
        HeavyBuyer = new Inte_CRM.Client
        {
            ClientId = a.Client.ClientId + 10,
            ClientName = a.Client.ClientName + "_heavy",
            CloudServer = new Inte_CRM.CloudServer
            {
                CloudServerId = a.Client.CloudServer.CloudServerId + 10,
                CloudServerName = a.Client.CloudServer.CloudServerName + "_heavy",
            }
        }
    };
r1 = query.ToList();
//SQL=>
//SELECT 
//t0.[OrderId] AS [OrderId],
//t0.[OrderNo] AS [OrderNo],
//t0.[Remark] AS [Remark],
//t0.[ClientId] AS [ClientId],
//t1.[ClientId] AS [ClientId1],
//t1.[ClientCode] AS [ClientCode],
//t1.[ClientName] AS [ClientName],
//t1.[State] AS [State],
//t1.[ActiveDate] AS [ActiveDate],
//t1.[CloudServerId] AS [CloudServerId],
//t2.[CloudServerId] AS [CloudServerId1],
//t2.[CloudServerName] AS [CloudServerName],
//t1.[ClientId] + 10 AS [ClientId2],
//t1.[ClientName] + N'_heavy' AS [ClientName1],
//t2.[CloudServerId] + 10 AS [CloudServerId2],
//t2.[CloudServerName] + N'_heavy' AS [CloudServerName1]
//FROM [CRM_SaleOrder] t0 
//LEFT JOIN [Bas_Client] t1 ON t0.[ClientId] = t1.[ClientId]
//LEFT JOIN [Sys_CloudServer] t2 ON t1.[CloudServerId] = t2.[CloudServerId]

4858.com 47

 

任何更加多示例在源码的 demo
中有详实表明,源码地址:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

正文首要分享:

 

框架作用演示

  • 表单数据绑定,分页展现–
  • 多少映射,查询–
  • SQL-MAP演示(请查看DAL层代码)–
  •  OQL查询(演示请看TestSqlMapEntity 项目)
  • 支撑工具,提供代码生成器和SQLMAP配置文件管理程序–(请看化解方案Tools目录)

  1. 完全流程、调用顺序图
  2. 基本代码的辨析

声明
  欢迎转发,但请保留小说原来出处:)
  博客园:
  农民四伯:

框架的适用原则

  • 率先你是懒人或许菜鸟,大牌请绕道;
  • 其次,你很喜爱平民化的本事,不是那种非MS等大厂提供的框架不用的技巧狂欢人员;
  • 最后,若是业主把你逼急了,建议您利用本框架,当然在此之前你得先熟习它,自身便是在那种状态下不顾项目COO的不予私行动用这套框架的,算是本框架的第三回商业项目标运用。(小编一位完毕了连串75%的代码开采,此外五人只写了1/4,项目经理最终才没话说)

停放阅读:《MyCAT 源码分析 —— 【单库单表】查询》。

 

框架使用的限定条件

OK,Let’s Go。

正文

批准限制

      
首先,请珍惜本框架的版权,本人能够有原则的绽开本框架的有的恐怕全体源码,假若您赚取了源码你能够4意对其修改但不能修改本框架的称号和版权归属,你
不得以将原始源码恐怕修改后的源码分发给任何第二方,假设您改改后,请向自身发送一份。假若你未从官方获得本框架的源码
,未经许可,不得采纳别的工具对本框架反向工程查看和改换源码。任何团体和民用都得以将本框架使用于别的商业类型,可以无偿应用本框架官方发布的最终DLL库和连锁工具,但你有任务向本身告知您利用本框架的中坚音信,比如公司名称,项目名称,项目手艺新闻等。本身不对你利用本框架形成的其它损失承担任
何权利。倘诺您区别意上述条款,请勿使用本框架!

本领限制

      
当前版本基于.NET贰.0之上平台,不支持实业对象对应的数量库表外键关系,OQL表达式不扶助多实体类查询,不扶助SQL的总括求和分组等,如有这个复杂查询供给,请使用SQL-MAP工夫。SQL-MAP
配置文件不扶助多个布局文件,但你能够将配备文件以嵌入式文件分散到七个DAL项目中。数据访问已经嵌入了
SqlServer,奥莱Db,ODBC,Oracle,SQLite等,就算您想提供任何数据库类型的走访,能够利用奥莱Db可能ODBC情势,也许承接本框架的数码访问类支出专用数据访问提供程序。

2. 主流程

  壹、作用实现

框架源码的得到

       你可以无偿向本人索取本框架的测试消除方案
,要是您喜爱并想获取本框架的百分百源码,请在线向本人发邮件联系:
dth197七@sohu.com 

       本身也欢迎你从地下门路获得本框架程序(不包罗源码
),只要你依照许可限制。

当试行跨库两表 Join SQL 时,经历的大约流程如下:

  fork 一份源码然后把下边代码出席源码(有些类限制了拜访成效域)

慈善行动

      
本身属福建洛阳人物,二〇一〇年华夏甘肃汶四川大学地震商丘也是重灾区,就算横祸已经过去一年多,但灾区重建照旧是多少个漫漫历程。因而笔者决定运用软件义卖格局,自个儿承诺,将本框架所获获益的八分之四捐募给灾区人民,请全体有慈善的人物鼎力援助!

4858.com 48

  SelectSQL.swift

框架应用的花色案例

200柒。四川某市测量绘制流程管理种类,PDF.NET Ver壹.0,职业流和消息保管某些;

二〇一〇。东京某房产备案管理体系,PDF.NET Ver壹.0,工作流部分;

二零一零。东方之珠某经济咨询企银多少运用类型,PDF.NE电视er二.0,作为系统焦点框架部分。

20十。XX银行XX市分行基金经营出售系统,PDF.NETVer四.0,作为系统宗旨框架部分。 

。。。越来越多成功案例等待你的落实:)

SQL 上,要求增加表明 /*!mycat:catlet=io.mycat.catlets.ShareJoin */
${SQL} 。RouteService#route(…) 解析注解 mycat:catlet 后,路由给
HintCatletHandler 作进一步处理。

import Foundation

    extension Database {

        public func prepareSelectSQL(on propertyConvertibleList: [PropertyConvertible], sql: String, values: [ColumnEncodableBase] = []) throws -> SelectSQL {
            return try SelectSQL(with: self, on: propertyConvertibleList, sql: sql, values: values)
        }

    }

    public final class SelectSQL {

        private final var core: Core
        final var optionalRecyclableHandleStatement: RecyclableHandleStatement?
        final var statement: StatementSelectSQL

        private let keys: [CodingTableKeyBase]
        private let values: [ColumnEncodableBase]

        private lazy var decoder = TableDecoder(keys, on: optionalRecyclableHandleStatement!)

        init(with core: Core, on propertyConvertibleList: [PropertyConvertible], sql: String, values: [ColumnEncodableBase]) throws {
            //TODO: Use generic to check all coding table keys conform to same root type
            keys = propertyConvertibleList.asCodingTableKeys()
            self.statement = StatementSelectSQL(sql: sql)
            self.core = core
            self.values = values
        }

        private func bindValues() throws {
            guard values.count > 0 else {
                return
            }
            let handleStatement = try lazyHandleStatement()
            for idx in 0..<values.count {
                handleStatement.bind(values[idx].archivedFundamentalValue(), toIndex: idx + 1)
            }
        }

        deinit {
            try? finalize()
        }

        /// Get all selected objects according to the `CodingTableKey`.
        ///
        /// - Returns: Table decodable objects according to the `CodingTableKey`
        /// - Throws: `Error`
        public func allObjects() throws -> [Any] {
            let rootType = keys[0].rootType as? TableDecodableBase.Type
            assert(rootType != nil, "\(keys[0].rootType) must conform to TableDecodable protocol.")
            var objects: [Any] = []
            try bindValues()
            while try next() {
                objects.append(try rootType!.init(from: decoder))
            }
            return objects
        }

        /// Get all selected objects.
        ///
        /// - Parameter type: Type of table decodable object
        /// - Returns: Table decodable objects.
        /// - Throws: `Error`
        public func allObjects<Object: TableDecodable>(of type: Object.Type = Object.self) throws -> [Object] {
            assert(keys is [Object.CodingKeys], "Properties must belong to \(Object.self).CodingKeys.")
            var objects: [Object] = []
            try bindValues()
            while try next() {
                objects.append(try Object.init(from: decoder))
            }
            return objects
        }

        final func finalize() throws {
            if let recyclableHandleStatement = optionalRecyclableHandleStatement {
                try recyclableHandleStatement.raw.finalize()
                optionalRecyclableHandleStatement = nil
            }
        }

        final func lazyHandleStatement() throws -> HandleStatement {
            if optionalRecyclableHandleStatement == nil {
                optionalRecyclableHandleStatement = try core.prepare(statement)
            }
            return optionalRecyclableHandleStatement!.raw
        }

        //Since `next()` may throw errors, it can't conform to `Sequence` protocol to fit a `for in` loop.
        @discardableResult
        public final func next() throws -> Bool {
            do {
                return try lazyHandleStatement().step()
            } catch let error {
                try? finalize()
                throw error
            }
        }

    }

    extension SelectSQL: CoreRepresentable {
        /// The tag of the related database.
        public final var tag: Tag? {
            return core.tag
        }

        /// The path of the related database.
        public final var path: String {
            return core.path
        }
    }

新版本消息

 

Ver 4.0 更新:

健全改写了实体类处理程序,功用升高拾倍;

革新实体类生成器,补助从 SQLSE福特ExplorerVE途睿欧 表字段表明变化实体类属性表达;

SqlMapDAL 协助外部接口定义;

简化了支撑多个SqlMap文件的处理情势;

SQL-MAP协理复杂查询的分页;

SQL-MAP改正了对存款和储蓄进程的支撑;

OQL帮助单行表达式语法(OQL.From(Entity).Select(….).Where(…).OrderBy(…).END);

实体类帮衬高功效分页;

优化了转移内部数据访问对象的频率(不再依赖于反射);

优化了别样操作的功能。

 

Ver 3.0 更新:

•周全改写了SqlMap模块,真正扶助SQL-实体类 映射
•全面调控了框架的命名空间,合并了根基程序集成为二个 PWMIS.Core.dll
•创新了自贰.0的话的Bug
•创新了代码生成器

Ver 2.0 更新:
•使用.NET 二.0技能改写原来有所的模块
•巩固了Web控件验证作用
•周全改写原有实体类,提供实体类生成器
•全面改写了OQL作用
•帮助.NET 二.0数据库连接配置

Ver 1.0 功能:
•提供SQL-MAP功能
•提供ORM功能,并提供OQL功能
•提供控件数据绑定作用
•提供高效分页控件
•提供控件数据证实际效果能

HintCatletHandler 获取表明对应的 Catlet
完成类,io.mycat.catlets.ShareJoin
就是里面一种完结(近年来也唯有那壹种落成),提供了跨库两表 Join
的职能。从类命名上看,ShareJoin 不小可能后续会提供整机的跨库多表的
Join 作用。

 

越来越多音讯

本框架官网
(新申请域名,要是不能够张开表明还在备案中,原网站:

自小编联系格局

QQ:45383850 (中绿医务人士)大概

mailto:bluedoctors@msn.com (抗震救济苦难)

PDF.NET 本领开采群:43十992九

连锁文书档案和越多消息请查看官网。

大旨代码如下:

  StatementSelectSQL.swift

// HintCatletHandler.java public RouteResultset route(SystemConfig sysConfig, SchemaConfig schema,                            int sqlType, String realSQL, String charset, ServerConnection sc,                            LayerCachePool cachePool, String hintSQLValue, int hintSqlType, Map hintMap)        throws SQLNonTransientException {    String cateletClass = hintSQLValue;    if (LOGGER.isDebugEnabled()) {        LOGGER.debug("load catelet class:" + hintSQLValue + " to run sql " + realSQL);    }    try {        Catlet catlet = (Catlet) MycatServer.getInstance().getCatletClassLoader().getInstanceofClass(cateletClass);        catlet.route(sysConfig, schema, sqlType, realSQL, charset, sc, cachePool);        catlet.processSQL(realSQL, new EngineCtx(sc.getSession2()));    } catch (Exception e) {        LOGGER.warn("catlet error " + e);        throw new SQLNonTransientException(e);    }    return null; }  
    import Foundation

    public final class StatementSelectSQL: Statement {

        public private(set) var description: String = ""
        public var statementType: StatementType {
            return .select
        }

        public init(sql: String) {
            self.description = sql
        }
    }

3. ShareJoin

 

现阶段支撑跨库两表 Join。ShareJoin 将 SQL 拆分成左表 SQL 和 右表
SQL,发送给各数据节点试行,汇总的数量据结果开始展览合后归来。

    UpdateSQL.swift

伪代码如下:

    import Foundation

    extension Database {

        public func prepareUpdateSQL(sql: String) throws -> UpdateSQL {
            return try UpdateSQL(with: self, sql: sql)
        }

    }

    /// The chain call for updating
    public final class UpdateSQL {
        private var core: Core
        private let statement: StatementUpdateSQL

        /// The number of changed rows in the most recent call.
        /// It should be called after executing successfully
        public var changes: Int?

        init(with core: Core, sql: String) throws {
            self.core = core
            self.statement = StatementUpdateSQL(sql: sql)
        }

        /// Execute the update chain call with row.
        ///
        /// - Parameter row: Column encodable row
        /// - Throws: `Error`
        public func execute(with row: [ColumnEncodableBase?] = []) throws {
            let recyclableHandleStatement: RecyclableHandleStatement = try core.prepare(statement)
            let handleStatement = recyclableHandleStatement.raw
            for (index, value) in row.enumerated() {
                let bindingIndex = index + 1
                handleStatement.bind(value?.archivedFundamentalValue(), toIndex: bindingIndex)
            }
            try handleStatement.step()
            changes = handleStatement.changes
        }
    }

    extension UpdateSQL: CoreRepresentable {

        /// The tag of the related database.
        public var tag: Tag? {
            return core.tag
        }

        /// The path of the related database.
        public var path: String {
            return core.path
        }
    }
// SELECT u.id, o.id FROM t_order o  // INNER JOIN t_user u ON o.uid = u.id // 【顺序】查询左表 String leftSQL = "SELECT o.id, u.id FROM t_order o"; List leftList = dn[0].select(leftSQL) + dn[1].select(leftSQL) + ... + dn[n].select(leftsql); // 【并行】查询右表 String rightSQL = "SELECT u.id FROM t_user u WHERE u.id IN (${leftList.uid})"; for (dn : dns) { // 此处是并行执行,使用回调逻辑     for (rightRecord : dn.select(rightSQL)) { // 查询右表         // 合并结果         for (leftRecord : leftList) {             if (leftRecord.uid == rightRecord.id) {                 write(leftRecord + leftRecord.uid 拼接结果);             }         }     } }  

 

实际上情状会进一步错综复杂,大家接下去一小点往下看。

    StatementUpdateSQL.swift  

3.1 JoinParser

    import Foundation

    public final class StatementUpdateSQL: Statement {

        public private(set) var description: String = ""
        public var statementType: StatementType {
            return .update
        }

        public init(sql: String) {
            self.description = sql
        }
    }

JoinParser 负责对 SQL 进行分析。全部流程如下:

 

4858.com 49

  二、使用 SQL 查询或更新数据

举个例证,/*!mycat:catlet=io.mycat.catlets.ShareJoin */ SELECT o.id,
u.username from t_order o join t_user u on o.uid = u.id;
解析后,TableFilter 结果如下:

    2.1  查询

4858.com 50

      database.prepareSelectSQL(User.Properties.Id, "SELECT id FROM users where id = ?", values: ["1"])
  • tName :表名
  • tAlia :表自定义命名
  • where :过滤条件
  • order :排序条件
  • parenTable :左连接的 Join 的表名。t_user表 在 join属性 的
    parenTable 为 “o”,即 t_order。
  • joinParentkey :左连接的 Join 字段
  • joinKey :join 字段。t_user表 在 join属性 为 id。
  • join :子 tableFilter。即,该表连接的左侧的表。
  • parent :和 join属性 相对。

      须要尤其注意的是只要回到
Codable 数据,SELECT 字段的逐条必须求和 CodingKeys
里的依次1致,不然数据会填充乱,可是用 WINQ 不会有其一难点。

看看此间,大家兴许有疑难,为何要把 SQL 解析成 TableFilter。JoinParser
依照 TableFilter 生成数据节点实行 SQL。代码如下:

    2.2  更新

// TableFilter.java public String getSQL() {    String sql = "";    // fields    for (Entry<String, String> entry : fieldAliasMap.entrySet()) {        String key = entry.getKey();        String val = entry.getValue();        if (val == null) {            sql = unionsql(sql, getFieldfrom(key), ",");        } else {            sql = unionsql(sql, getFieldfrom(key) + " as " + val, ",");        }    }    // where    if (parent == null) {    // on/where 等于号左边的表        String parentJoinKey = getJoinKey(true);        // fix sharejoin bug:        // (AbstractConnection.java:458) -close connection,reason:program err:java.lang.IndexOutOfBoundsException:        // 原因是左表的select列没有包含 join 列,在获取结果时报上面的错误        if (sql != null && parentJoinKey != null &&                !sql.toUpperCase().contains(parentJoinKey.trim().toUpperCase())) {            sql += ", " + parentJoinKey;        }        sql = "select " + sql + " from " + tName;        if (!(where.trim().equals(""))) {            sql += " where " + where.trim();        }    } else {    // on/where 等于号右边边的表        if (allField) {            sql = "select " + sql + " from " + tName;        } else {            sql = unionField("select " + joinKey, sql, ",");            sql = sql + " from " + tName;            //sql="select "+joinKey+","+sql+" from "+tName;        }        if (!(where.trim().equals(""))) {            sql += " where " + where.trim() + " and (" + joinKey + " in %s )";        } else {            sql += " where " + joinKey + " in %s ";        }    }    // order    if (!(order.trim().equals(""))) {        sql += " order by " + order.trim();    }    // limit    if (parent == null) {        if ((rowCount > 0) && (offset > 0)) {            sql += " limit" + offset + "," + rowCount;        } else {            if (rowCount > 0) {                sql += " limit " + rowCount;            }        }    }    return sql; }  
                let updateSQL = try database.prepareUpdateSQL(sql: "UPDATE conversations SET last_message_id = (select id from messages where conversation_id = ? order by created_at DESC limit 1) WHERE conversation_id = ?")
                try updateSQL.execute(with: [conversationId, conversationId])
  • 当 parent 为空时,即on/where 等于号左边的表。例如:select id, uid
    from t_order。
  • 当 parent 不为空时,即on/where 等于号左边的表。例如:select id,
    username from t_user where id in (1, 2, 3)。

  

3.2 ShareJoin.processSQL(…)

 结束

当 SQL 解析完后,生成右侧的表试行的
SQL,发送给对应的数额节点查询数据。轮廓流程如下:

  近年来用了壹段时间未有发现怎么难点,除了前方那么些注意顺序难点,WINQ
就是拼 SQL 语句搞不懂官方为什么不直接支持三个,尽管能支撑全体 SQL
改起来也很麻烦,而且代码量繁多。

4858.com 51

当 SQL 为 /*!mycat:catlet=io.mycat.catlets.ShareJoin */ SELECT o.id,
u.username from t_order o join t_user u on o.uid = u.id; 时, sql =
getSql() 的回来结果为 select id, uid from t_order。

转移右边的表实践的 SQL
后,顺序依次依次发送给对应的数码节点查询数据。具体顺序查询是怎么落到实处的,大家来看下章
BatchSQLJob。

3.3 BatchSQLJob

4858.com 52

EngineCtx 对 BatchSQLJob 封装,提供上层多少个方法:

  • executeNativeSQLSequnceJob :顺序(非并发)在各种数据节点实施SQL职责
  • executeNativeSQLParallJob :并发在种种数据节点实施SQL职务

基本代码如下:

// EngineCtx.java public void executeNativeSQLSequnceJob(String[] dataNodes, String sql,         SQLJobHandler jobHandler) {     for (String dataNode : dataNodes) {         SQLJob job = new SQLJob(jobId.incrementAndGet(), sql, dataNode,                 jobHandler, this);         bachJob.addJob(job, false);     } }  public void executeNativeSQLParallJob(String[] dataNodes, String sql,         SQLJobHandler jobHandler) {     for (String dataNode : dataNodes) {         SQLJob job = new SQLJob(jobId.incrementAndGet(), sql, dataNode,                 jobHandler, this);         bachJob.addJob(job, true);     } }  

BatchSQLJob
通超过实际践中职分列表、待施行职务列表来贯彻顺序/并发实践职责。主题代码如下:

// BatchSQLJob.java /** * 执行中任务列表 */ private ConcurrentHashMap<Integer, SQLJob> runningJobs = new ConcurrentHashMap<Integer, SQLJob>(); /** * 待执行任务列表 */ private ConcurrentLinkedQueue<SQLJob> waitingJobs = new ConcurrentLinkedQueue<SQLJob>();  public void addJob(SQLJob newJob, boolean parallExecute) {    if (parallExecute) {        runJob(newJob);    } else {        waitingJobs.offer(newJob);        if (runningJobs.isEmpty()) { // 若无正在执行中的任务,则从等待队列里获取任务进行执行。            SQLJob job = waitingJobs.poll();            if (job != null) {                runJob(job);            }        }    } }  public boolean jobFinished(SQLJob sqlJob) {     runningJobs.remove(sqlJob.getId());     SQLJob job = waitingJobs.poll();     if (job != null) {         runJob(job);         return false;     } else {         if (noMoreJobInput) {             return runningJobs.isEmpty() && waitingJobs.isEmpty();         } else {             return false;         }     } }  
  • 种种推行时,当 runningJobs 存在实施中的职分时,#addJob(…)
    时,不马上实行,增添到 waitingJobs。当 SQLJob
    完毕时,顺序调用下1个职责。
  • 出现实施时,#addJob(…) 时,立刻实行。

SQLJob SQL 异步推行职责。其 jobHandler(SQLJobHandler) 属性,在 SQL
试行有再次回到结果时,会进行回调,从而达成异步执行。

在 ShareJoin 里,SQLJobHandler
有多个落到实处:ShareDBJoinHandler、ShareRowOutPutDataHandler。前者,左边的表试行的
SQL 回调;后者,右侧的表实行的 SQL 回调。

4858.com 53

3.4 ShareDBJoinHandler

ShareDBJoinHandler,左侧的表推行的 SQL 回调。流程如下:

4858.com 54

  • #田野同志EofResponse(…) :接收数据节点重返的 田野s,放入内部存款和储蓄器。
  • #rowResponse(…) :接收数据节点重返的 row,放入内部存款和储蓄器。
  • #rowEofResponse(…) :接收完三个数量节点重临全体的
    row。当有着数据节点都做到 SQL 试行时,提交左侧的表实行的 SQL
    任务,并行施行,即图中#createQryJob(…)。

当 SQL 为 /*!mycat:catlet=io.mycat.catlets.ShareJoin */ SELECT o.id,
u.username from t_order o join t_user u on o.uid = u.id; 时, sql =
getChildSQL() 的回来结果为 select id, username from t_user where id in
(1, 2, 3)。

基本代码如下:

// ShareJoin.java private void createQryJob(int batchSize) {    int count = 0;    Map<String, byte[]> batchRows = new ConcurrentHashMap<String, byte[]>();    String theId = null;    StringBuilder sb = new StringBuilder().append('(');    String svalue = "";    for (Map.Entry<String, String> e : ids.entrySet()) {        theId = e.getKey();        byte[] rowbyte = rows.remove(theId);        if (rowbyte != null) {            batchRows.put(theId, rowbyte);        }        if (!svalue.equals(e.getValue())) {            if (joinKeyType == Fields.FIELD_TYPE_VAR_STRING                    || joinKeyType == Fields.FIELD_TYPE_STRING) { // joinkey 为varchar                sb.append("'").append(e.getValue()).append("'").append(','); // ('digdeep','yuanfang')            } else { // 默认joinkey为int/long                sb.append(e.getValue()).append(','); // (1,2,3)            }        }        svalue = e.getValue();        if (count++ > batchSize) {            break;        }    }    if (count == 0) {        return;    }    jointTableIsData = true;    sb.deleteCharAt(sb.length() - 1).append(')');    String sql = String.format(joinParser.getChildSQL(), sb);    getRoute(sql);    ctx.executeNativeSQLParallJob(getDataNodes(), sql, new ShareRowOutPutDataHandler(this, fields, joinindex, joinParser.getJoinRkey(), batchRows, ctx.getSession())); }  

3.5 ShareRowOutPutDataHandler

ShareRowOutPutDataHandler,右侧的表施行的 SQL 回调。流程如下:

4858.com 55

  • #田野先生EofResponse(…) :接收数据节点再次回到的 田野s,重回 header 给
    MySQL Client。
  • #rowResponse(…) :接收数据节点重回的
    row,相配左表的笔录,重回合并后回来的 row 给 MySQL Client。
  • #rowEofResponse(…) :当有着 row 都回到完后,重返 eof 给 MySQL
    Client。

中央代码如下:

// ShareRowOutPutDataHandler.java public boolean onRowData(String dataNode, byte[] rowData) {    RowDataPacket rowDataPkgold = ResultSetUtil.parseRowData(rowData, bfields);    //拷贝一份batchRows    Map<String, byte[]> batchRowsCopy = new ConcurrentHashMap<String, byte[]>();    batchRowsCopy.putAll(arows);    // 获取Id字段,    String id = ByteUtil.getString(rowDataPkgold.fieldValues.get(joinR));    // 查找ID对应的A表的记录    byte[] arow = getRow(batchRowsCopy, id, joinL);    while (arow != null) {        RowDataPacket rowDataPkg = ResultSetUtil.parseRowData(arow, afields);//ctx.getAllFields());        for (int i = 1; i < rowDataPkgold.fieldCount; i++) {            // 设置b.name 字段            byte[] bname = rowDataPkgold.fieldValues.get(i);            rowDataPkg.add(bname);            rowDataPkg.addFieldCount(1);        }        // huangyiming add        MiddlerResultHandler middlerResultHandler = session.getMiddlerResultHandler();        if (null == middlerResultHandler) {            ctx.writeRow(rowDataPkg);        } else {            if (middlerResultHandler instanceof MiddlerQueryResultHandler) {                byte[] columnData = rowDataPkg.fieldValues.get(0);                if (columnData != null && columnData.length > 0) {                    String rowValue = new String(columnData);                    middlerResultHandler.add(rowValue);                }                //}            }         }        arow = getRow(batchRowsCopy, id, joinL);    }    return false; }  

4. 彩蛋

一般来讲是本文涉及到的主导类,有意思味的同桌能够翻1翻。

4858.com 56

ShareJoin 别的不援救的作用:

  1. 只帮忙 inner join,不扶助 left join、right join 等等连接。
  2. 不支持 order by。
  3. 不扶助 group by 以及 相关聚合函数。
  4. 不畏 join 左表的字段未注解为回到 田野(field)s 也会回来。

恩,MyCAT 弱XA 源码继续走起!

【编辑推荐】

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有