├── .gitattributes
├── .gitignore
├── Dapper.Extensions.Tests
├── Dapper.Extensions.Tests.xproj
├── DapperExtensionsTest.cs
├── Entitys.cs
├── Properties
│ └── AssemblyInfo.cs
├── WhereExpressionTest.cs
└── project.json
├── Dapper.Extensions.sln
├── README.md
├── global.json
└── src
└── Dapper.Extensions
├── ActiveAttribute.cs
├── Dapper.Extensions.xproj
├── DapperSort.cs
├── FieldsFormater.cs
├── IOperatorWhere.cs
├── OperatorWhereObject.cs
├── PageCondition.cs
├── PageView.cs
├── Parameter.cs
├── Properties
└── AssemblyInfo.cs
├── SQLMethod.cs
├── SqlMapperExtensions.cs
├── SqlMethodNameCallBack.cs
├── SqlTranslateFormater.cs
└── project.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Microsoft Azure ApplicationInsights config file
170 | ApplicationInsights.config
171 |
172 | # Windows Store app package directory
173 | AppPackages/
174 | BundleArtifacts/
175 |
176 | # Visual Studio cache files
177 | # files ending in .cache can be ignored
178 | *.[Cc]ache
179 | # but keep track of directories ending in .cache
180 | !*.[Cc]ache/
181 |
182 | # Others
183 | ClientBin/
184 | [Ss]tyle[Cc]op.*
185 | ~$*
186 | *~
187 | *.dbmdl
188 | *.dbproj.schemaview
189 | *.pfx
190 | *.publishsettings
191 | node_modules/
192 | orleans.codegen.cs
193 |
194 | # RIA/Silverlight projects
195 | Generated_Code/
196 |
197 | # Backup & report files from converting an old project file
198 | # to a newer Visual Studio version. Backup files are not needed,
199 | # because we have git ;-)
200 | _UpgradeReport_Files/
201 | Backup*/
202 | UpgradeLog*.XML
203 | UpgradeLog*.htm
204 |
205 | # SQL Server files
206 | *.mdf
207 | *.ldf
208 |
209 | # Business Intelligence projects
210 | *.rdl.data
211 | *.bim.layout
212 | *.bim_*.settings
213 |
214 | # Microsoft Fakes
215 | FakesAssemblies/
216 |
217 | # GhostDoc plugin setting file
218 | *.GhostDoc.xml
219 |
220 | # Node.js Tools for Visual Studio
221 | .ntvs_analysis.dat
222 |
223 | # Visual Studio 6 build log
224 | *.plg
225 |
226 | # Visual Studio 6 workspace options file
227 | *.opt
228 |
229 | # Visual Studio LightSwitch build output
230 | **/*.HTMLClient/GeneratedArtifacts
231 | **/*.DesktopClient/GeneratedArtifacts
232 | **/*.DesktopClient/ModelManifest.xml
233 | **/*.Server/GeneratedArtifacts
234 | **/*.Server/ModelManifest.xml
235 | _Pvt_Extensions
236 |
237 | # LightSwitch generated files
238 | GeneratedArtifacts/
239 | ModelManifest.xml
240 |
241 | # Paket dependency manager
242 | .paket/paket.exe
243 |
244 | # FAKE - F# Make
245 | .fake/
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/Dapper.Extensions.Tests.xproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 14.0
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 |
7 |
8 |
9 | b6913d7c-21a4-4413-b1cd-68f1a3fbd57d
10 | Dapper.Extensions.Tests
11 | .\obj
12 | .\bin\
13 | v4.5.2
14 |
15 |
16 | 2.0
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/DapperExtensionsTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Data;
3 | using System.Data.SqlClient;
4 | using System.Linq;
5 | using Dapper.Contrib.Extensions;
6 | using Xunit;
7 |
8 | namespace Dapper.Extensions.Tests
9 | {
10 | public class DapperExtensionsTest
11 | {
12 | private IDbConnection GetOpenConnection()
13 | {
14 | var connection = new SqlConnection(@"");
15 | //connection.Open();
16 | return connection;
17 | }
18 |
19 | [Fact]
20 | public void GetCustomerById()
21 | {
22 | using (var connect = GetOpenConnection())
23 | {
24 | var customer = connect.Get(1);
25 | Assert.Equal(customer.CustomerID, 1);
26 | Assert.Equal(customer.CustomerName, "A1");
27 | Assert.Equal(customer.CustomerNumber, "9999");
28 | Assert.Equal(customer.CustomerCity, "x1");
29 | }
30 | }
31 |
32 | [Fact]
33 | public void GetCustomerByQuery()
34 | {
35 | using (var connect = GetOpenConnection())
36 | {
37 | var customer = connect.Get(c => c.CustomerID == 1);
38 | Assert.Equal(customer.CustomerID, 1);
39 | Assert.Equal(customer.CustomerName, "A1");
40 | Assert.Equal(customer.CustomerNumber, "9999");
41 | Assert.Equal(customer.CustomerCity, "x1");
42 | }
43 | }
44 |
45 |
46 | [Fact]
47 | public void GetCustomerListByQuery()
48 | {
49 | using (var connect = GetOpenConnection())
50 | {
51 | var customers = connect.GetAll(c => c.CustomerID <= 50);
52 | Assert.Equal(customers.Count(), 50);
53 | }
54 | }
55 |
56 |
57 | [Fact]
58 | public void InsertCustomer()
59 | {
60 | using (var connect = GetOpenConnection())
61 | {
62 | int count = connect.QuerySingle("select count(1) from Customers2");
63 |
64 |
65 | var customer = new CustomersEntity() { CustomerName = "A1", CustomerCity = "x1", CustomerNumber = "9999" };
66 |
67 | long id = connect.Insert(customer);
68 |
69 | Assert.Equal(id - 2, count);
70 | }
71 | }
72 |
73 |
74 | ///
75 | /// 注意:Dapper自带的Update语句;不能只更新某些字段
76 | ///
77 | [Fact]
78 | public void UpdateCustomer()
79 | {
80 | using (var connect = GetOpenConnection())
81 | {
82 |
83 | var customer = new CustomersEntity() { CustomerID = 1, CustomerName = "A1", CustomerCity = "x1", CustomerNumber = "9999" };
84 | //更新实体,不能只更新某些字段
85 | bool s = connect.Update(customer);
86 |
87 | Assert.Equal(s, true);
88 | }
89 | }
90 |
91 |
92 | ///
93 | /// 注意:咱们框架里扩展的复杂Update语句,保证只更新表达式中的字段值
94 | ///
95 | [Fact]
96 | public void SimpleUpdateExpressionMethodTest1()
97 | {
98 | using (var connect = GetOpenConnection())
99 | {
100 | //更新一个表达式实体,保证只更新表达式中的字段值
101 | //IOperatorWhere.Where(exp);
102 | var updater = connect.Update(c => new CustomersEntity()
103 | {
104 | CustomerName = "hello",
105 | CustomerCity = "x1"
106 | })
107 | .Where(c => c.CustomerID == 2);
108 |
109 | string sql = updater.SQL;
110 |
111 | Assert.Equal(sql,
112 | "Update Customers2 SET CustomerName=@CustomerName,CustomerCity=@CustomerCity Where CustomerID = 2");
113 |
114 | //IOperatorWhere.Go();
115 | //API采用 Update({new entity expression}).Where(expression).Go()的链式使用方式。
116 | bool ret = updater.Go();
117 |
118 | Assert.Equal(ret, true);
119 | }
120 | }
121 |
122 | [Fact]
123 | public void SimpleUpdateExpressionMethodTest2()
124 | {
125 | using (var connect = GetOpenConnection())
126 | {
127 | // 匿名对象1
128 | var entity1 = new { CustomerName = "hello", CustomerCity = "x1" };
129 |
130 | var updater1 = connect.Update(entity1)
131 | .Where(c => c.CustomerID == 2);
132 |
133 | string sql1 = updater1.SQL;
134 | Assert.Equal(sql1,
135 | "Update Customers2 SET CustomerName=@CustomerName,CustomerCity=@CustomerCity Where CustomerID = 2");
136 |
137 | // 匿名对象2
138 | CustomersEntity entity2 = new CustomersEntity { CustomerName = "hello", CustomerCity = "x1", CustomerNumber = "x123" };
139 |
140 | var updater2 = connect.Update(new { entity2.CustomerName, entity2.CustomerCity })
141 | .Where(c => c.CustomerID == 2);
142 |
143 | string sql2 = updater2.SQL;
144 | Assert.Equal(sql2,
145 | "Update Customers2 SET CustomerName=@CustomerName,CustomerCity=@CustomerCity Where CustomerID = 2");
146 |
147 | // 实体对象/全字段更新且忽略标记了Computed特性的属性
148 | var updater3 = connect.Update(entity2)
149 | .Where(c => c.CustomerID == 2);
150 | string sql3 = updater3.SQL;
151 | }
152 | }
153 |
154 |
155 |
156 | ///
157 | /// 注意:Dapper扩展Update语句;用于更新IsActive字段
158 | ///
159 | [Fact]
160 | public void SetActiveTest()
161 | {
162 | using (var connect = GetOpenConnection())
163 | {
164 |
165 | bool s = connect.SetActive(1, true);
166 |
167 | Assert.Equal(s, true);
168 | }
169 | }
170 |
171 |
172 | ///
173 | /// 注意:Dapper扩展Update语句;用于更新IsActive字段
174 | ///
175 | [Fact]
176 | public void SetActiveTest2()
177 | {
178 | using (var connect = GetOpenConnection())
179 | {
180 | var customer = new CustomersEntity() { CustomerID = 2, IsActive = false };
181 | bool s = connect.SetActive(customer);
182 |
183 | Assert.Equal(s, true);
184 | }
185 | }
186 |
187 | ///
188 | /// 扩展Dapper默认Query方法支持Expression查询
189 | ///
190 | [Fact]
191 | public void QueryWithSortCustomer()
192 | {
193 | CustomersEntity entity = null;
194 | DapperSort sort = new DapperSort()
195 | {
196 | new Sort(index:1,field:nameof(entity.CustomerCity),sortType:ESortType.Asc),
197 | new Sort(index:0,field:nameof(entity.CustomerName),sortType:ESortType.Desc)
198 | };
199 |
200 | using (var connect = GetOpenConnection())
201 | {
202 | var customer = connect.Query(c => c.CustomerID == 1, null, sort);
203 | }
204 | }
205 |
206 | ///
207 | /// 查询部分字段
208 | ///
209 | [Fact]
210 | public void QueryPartial()
211 | {
212 | CustomersEntity entity = null;
213 | DapperSort sort = new DapperSort()
214 | {
215 | new Sort(index:1,field:nameof(entity.CustomerCity),sortType:ESortType.Asc),
216 | new Sort(index:0,field:nameof(entity.CustomerName),sortType:ESortType.Desc)
217 | };
218 |
219 | using (var connect = GetOpenConnection())
220 | {
221 | var customer = connect.Query(c => c.CustomerID == 1,
222 | c => new
223 | {
224 | c.CustomerCity,
225 | c.CustomerName
226 | }, sort);
227 | }
228 | }
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/Entitys.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Dapper.Contrib.Extensions;
6 |
7 | namespace Dapper.Extensions.Tests
8 | {
9 | [Table("Customers2")]
10 | public partial class CustomersEntity
11 | {
12 |
13 | [Key]
14 |
15 | ///
16 | ///
17 | ///
18 | public Int32 CustomerID { set; get; }
19 |
20 | ///
21 | ///
22 | ///
23 | public String CustomerNumber { set; get; }
24 |
25 | ///
26 | ///
27 | ///
28 | public String CustomerName { set; get; }
29 |
30 | ///
31 | ///
32 | ///
33 | public String CustomerCity { set; get; }
34 |
35 | [Active]
36 |
37 | ///
38 | ///
39 | ///
40 | public Nullable IsActive { set; get; }
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("Dapper.Extensions.Tests")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("b6913d7c-21a4-4413-b1cd-68f1a3fbd57d")]
20 |
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/WhereExpressionTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq.Expressions;
5 | using Dapper;
6 | using Dapper.Contrib;
7 | using Dapper.Contrib.Extensions;
8 | using Dapper.Extensions;
9 | using Dapper.Extensions.Tests;
10 | using Xunit;
11 | using System.Linq;
12 |
13 | namespace Dapper.Extensions.Tests
14 | {
15 |
16 | public class WhereExpressionTest
17 | {
18 | [Fact]
19 | public void SimpleWhereTest1()
20 | {
21 | Expression> queryExp1 = ct => ct.CustomerID < 50 && ct.CustomerCity == "B-City";
22 |
23 | var translate = new SqlTranslateFormater();
24 | string sql = translate.Translate(queryExp1);
25 |
26 | Assert.Equal(sql, "CustomerID < 50 AND CustomerCity = 'B-City'");
27 |
28 | }
29 |
30 | [Fact]
31 | public void SimpleWhereTest2()
32 | {
33 | Expression> queryExp1 = ct => ct.CustomerID == 1 &&
34 | (ct.CustomerCity == "B-City" || ct.CustomerNumber == "0000");
35 |
36 | var translate = new SqlTranslateFormater();
37 | string sql = translate.Translate(queryExp1);
38 |
39 | Assert.Equal(sql, "CustomerID = 1 AND (CustomerCity = 'B-City' OR CustomerNumber = '0000')");
40 |
41 | }
42 |
43 | [Fact]
44 | public void SimpleWhereMethodTest1()
45 | {
46 | Expression> queryExp1 = ct => ct.CustomerID <= 50 && (SQLMethod.IsNull(ct.CustomerCity));
47 |
48 | var translate = new SqlTranslateFormater();
49 | string sql = translate.Translate(queryExp1);
50 |
51 | Assert.Equal(sql, "CustomerID <= 50 AND CustomerCity is NULL");
52 |
53 | }
54 |
55 |
56 | [Fact]
57 | public void SimpleWhereMethodTest2()
58 | {
59 | Expression> queryExp1 = ct => ct.CustomerID <= 50 && (SQLMethod.IsNull(ct.CustomerCity));
60 |
61 | var translate = new SqlTranslateFormater();
62 | string sql = translate.Translate(queryExp1);
63 |
64 | Assert.Equal(sql, "CustomerID <= 50 AND CustomerCity is NULL");
65 |
66 | }
67 |
68 |
69 | [Fact]
70 | public void WhereMethodForParametersTest()
71 | {
72 | TestValueTypeParam(50);
73 | }
74 |
75 | private void TestValueTypeParam(int id)
76 | {
77 | Expression> queryExp1 = ct => ct.CustomerID <= id && (SQLMethod.IsNull(ct.CustomerCity));
78 |
79 | var translate = new SqlTranslateFormater();
80 | string sql = translate.Translate(queryExp1);
81 |
82 | Assert.Equal(sql, "CustomerID <= 50 AND CustomerCity is NULL");
83 | }
84 |
85 | [Fact]
86 | public void WhereMethodForParametersTest2()
87 | {
88 | TestEntityParam(new TestValue { Id = 50 });
89 | }
90 |
91 | private void TestEntityParam(TestValue v)
92 | {
93 | Expression> queryExp1 = ct => ct.CustomerID <= v.Id && (SQLMethod.IsNull(ct.CustomerCity));
94 |
95 | var translate = new SqlTranslateFormater();
96 | string sql = translate.Translate(queryExp1);
97 |
98 | Assert.Equal(sql, "CustomerID <= 50 AND CustomerCity is NULL");
99 | }
100 |
101 | [Fact]
102 | public void SimpleWhereMethodTest3()
103 | {
104 | //IEnumerable ids = new List() { 40, 50 };//通过测试
105 | //int[] ids = new[] {40, 50};//通过测试
106 | List ids = new List() { 40, 50 };//通过测试
107 |
108 | Expression> queryExp1 = ct => ids.Contains(ct.CustomerID) && (SQLMethod.IsNull(ct.CustomerCity));
109 |
110 | var translate = new SqlTranslateFormater();
111 | string sql = translate.Translate(queryExp1);
112 |
113 | Assert.Equal(sql, "CustomerID In (40,50) AND CustomerCity is NULL");
114 |
115 | }
116 |
117 |
118 | }
119 |
120 | public class TestValue
121 | {
122 | public int Id { set; get; }
123 | }
124 |
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/Dapper.Extensions.Tests/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.0-*",
3 | "buildOptions": {
4 | "debugType": "portable"
5 | },
6 | "dependencies": {
7 | "Dapper.Extensions": "1.0.0-*",
8 | "Dapper": "1.50.2",
9 | "Dapper.Contrib": "1.50.0",
10 | "System.Data.Common": "4.1.0",
11 | "xunit": "2.2.0-beta2-build3300",
12 | "dotnet-test-xunit": "2.2.0-preview2-build1029"
13 | },
14 | "testRunner": "xunit"
15 | ,
16 | "frameworks": {
17 | "netcoreapp1.0": {
18 | "dependencies": {
19 | "Microsoft.NETCore.App": {
20 | "type": "platform",
21 | "version": "1.0.0"
22 | }
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Dapper.Extensions.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BD0FD322-C606-4ADE-9483-F1E0644BF63E}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A1F5B0F2-8388-42F0-A616-129E75AABAC5}"
9 | ProjectSection(SolutionItems) = preProject
10 | global.json = global.json
11 | EndProjectSection
12 | EndProject
13 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dapper.Extensions", "src\Dapper.Extensions\Dapper.Extensions.xproj", "{F892188E-C751-4BB2-91BA-75B27236C9CD}"
14 | EndProject
15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B7E8B5AA-8505-4A19-B195-50571030C690}"
16 | EndProject
17 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Dapper.Extensions.Tests", "Dapper.Extensions.Tests\Dapper.Extensions.Tests.xproj", "{B6913D7C-21A4-4413-B1CD-68F1A3FBD57D}"
18 | EndProject
19 | Global
20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
21 | Debug|Any CPU = Debug|Any CPU
22 | Release|Any CPU = Release|Any CPU
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {F892188E-C751-4BB2-91BA-75B27236C9CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {F892188E-C751-4BB2-91BA-75B27236C9CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {F892188E-C751-4BB2-91BA-75B27236C9CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {F892188E-C751-4BB2-91BA-75B27236C9CD}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {B6913D7C-21A4-4413-B1CD-68F1A3FBD57D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {B6913D7C-21A4-4413-B1CD-68F1A3FBD57D}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {B6913D7C-21A4-4413-B1CD-68F1A3FBD57D}.Release|Any CPU.ActiveCfg = Release|Any CPU
32 | {B6913D7C-21A4-4413-B1CD-68F1A3FBD57D}.Release|Any CPU.Build.0 = Release|Any CPU
33 | EndGlobalSection
34 | GlobalSection(SolutionProperties) = preSolution
35 | HideSolutionNode = FALSE
36 | EndGlobalSection
37 | GlobalSection(NestedProjects) = preSolution
38 | {F892188E-C751-4BB2-91BA-75B27236C9CD} = {BD0FD322-C606-4ADE-9483-F1E0644BF63E}
39 | {B6913D7C-21A4-4413-B1CD-68F1A3FBD57D} = {B7E8B5AA-8505-4A19-B195-50571030C690}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dapper.Extensions
2 | YOYOFx中使用的Dapper扩展
3 | ###1. Get Entity:
4 | ```javascript
5 | using (var connect = GetOpenConnection())
6 | {
7 | var customer = connect.Get(1);
8 | var customer1 = connect.Get(c=>c.CustomerID == 1);
9 | }
10 | ```
11 |
12 | ###2. Insert Entity:
13 | ```javascript
14 | using (var connect = GetOpenConnection())
15 | {
16 | int count = connect.QuerySingle("select count(1) from Customers2");
17 | var customer = new CustomersEntity() { CustomerName = "A1", CustomerCity = "x1" , CustomerNumber = "9999"};
18 | long id = connect.Insert(customer);
19 | }
20 | ```
21 |
22 | ###3. Update Entity:
23 | ```javascript
24 | using (var connect = GetOpenConnection())
25 | {
26 | var customer = new CustomersEntity() { CustomerID = 1 , CustomerName = "A1", CustomerCity = "x1", CustomerNumber = "9999" };
27 | //1.更新实体,不能只更新某些字段
28 | bool s = connect.Update(customer);
29 | //2.更新一个表达式实体,保证只更新表达式中的字段值
30 | //IOperatorWhere.Where(exp).Go();
31 | var updater = connect.Update(c => new CustomersEntity
32 | {
33 | CustomerName = "hello",
34 | CustomerCity = "x1"
35 | });
36 | bool ret = updater.Go();
37 | }
38 | ```
39 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "projects": [ "src", "test" ],
3 | "sdk": {
4 | "version": "1.0.0-preview2-003121"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/ActiveAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Dapper.Extensions
8 | {
9 | ///
10 | /// 逻辑删除标记
11 | ///
12 | public class ActiveAttribute : Attribute
13 | {
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/Dapper.Extensions.xproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 14.0
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 |
7 |
8 |
9 |
10 | f892188e-c751-4bb2-91ba-75b27236c9cd
11 | Dapper.Extensions
12 | .\obj
13 | .\bin\
14 | v4.5.2
15 |
16 |
17 |
18 | 2.0
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/DapperSort.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Dapper.Extensions
8 | {
9 | ///
10 | /// 排序对象
11 | ///
12 | public class DapperSort : List
13 | {
14 | public override string ToString()
15 | {
16 | StringBuilder sb = new StringBuilder();
17 | this.Sort(new SortCompair());
18 | for (int i = 0; i < this.Count; i++)
19 | {
20 | sb.AppendFormat("{0} {1}", this[i].Field, this[i].ESortType);
21 | if (i < this.Count - 1)
22 | {
23 | sb.Append(", ");
24 | }
25 | }
26 | return sb.ToString();
27 | }
28 | }
29 |
30 | public class SortCompair : IComparer
31 | {
32 | public int Compare(Sort x, Sort y)
33 | {
34 | return x.Index - y.Index;
35 | }
36 | }
37 |
38 | public class Sort
39 | {
40 | public Sort(int index, string field, ESortType sortType)
41 | {
42 | Index = index;
43 | Field = field;
44 | ESortType = sortType;
45 | }
46 |
47 | public int Index { get; set; }
48 | public string Field { get; set; }
49 | public ESortType ESortType { get; set; }
50 | }
51 |
52 | public enum ESortType
53 | {
54 | Asc = 1,
55 | Desc = 2
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/FieldsFormater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 |
6 | namespace Dapper.Extensions
7 | {
8 | ///
9 | /// 访问 o => new obj{ ID = "1" },表达式的解析器
10 | ///
11 | public class FieldsFormater : ExpressionVisitor
12 | {
13 | ///
14 | /// sql server prefix of the paramter name SQLSERVER的参数修正符
15 | ///
16 | public string ParamPrefix => "@";
17 |
18 | public FieldsFormater()
19 | {
20 |
21 | }
22 | ///
23 | /// 解析后得到的参数如 [ { key: "ID" Value: "1" } , ... ]
24 | ///
25 | Dictionary parameters = new Dictionary();
26 |
27 | ///
28 | /// 访问常量表达式,将字段和值添加到参数列表中。
29 | ///
30 | /// 表达式节点
31 | /// 字段名
32 | ///
33 | protected Expression VisitConstant(ConstantExpression node,string fieldName)
34 | {
35 | if (parameters.Keys.Any(k => k == fieldName))
36 | parameters[fieldName].Value = node.Value;
37 | else
38 | {
39 | parameters.Add(fieldName, new Parameter(ParamPrefix + fieldName, node.Value));
40 | }
41 | return base.VisitConstant(node);
42 | }
43 |
44 | //将右值表达式如 ID = Convert(i) 直接通过编译计算出来
45 | protected Expression MyVisitMember(MemberExpression node, string fieldName)
46 | {
47 | LambdaExpression lambda = Expression.Lambda(node);
48 | var fn = lambda.Compile();
49 | VisitConstant(Expression.Constant(fn.DynamicInvoke(null), node.Type), fieldName);
50 | return base.VisitMember(node);
51 | }
52 |
53 | ///
54 | /// 访问成员,如 ID = 1 时。
55 | ///
56 | ///
57 | ///
58 | protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
59 | {
60 | string propertyName = node.Member.Name;
61 | string fieldName = propertyName;
62 |
63 | if (node.Expression.NodeType == ExpressionType.Call)
64 | {
65 | VisitMethodCall((MethodCallExpression)node.Expression,fieldName);
66 | }
67 | else if (node.Expression.NodeType == ExpressionType.Convert)
68 | {
69 | var ue = node.Expression as UnaryExpression;
70 | var call = ue.Operand as MethodCallExpression;
71 |
72 | if (call != null)
73 | this.VisitMethodCall(call, fieldName);
74 | else
75 | this.MyVisitMember(ue.Operand as MemberExpression,fieldName);
76 | }
77 | else
78 | {
79 | parameters.Add(fieldName, new Parameter(ParamPrefix + fieldName, null));
80 | var constant = node.Expression as ConstantExpression;
81 | if (constant != null)
82 | VisitConstant(constant, fieldName);
83 | else
84 | {
85 | LambdaExpression lambda = Expression.Lambda(node.Expression);
86 | var fn = lambda.Compile();
87 | VisitConstant(Expression.Constant(fn.DynamicInvoke(null), node.Expression.Type), fieldName);
88 | }
89 | }
90 | return node;
91 | }
92 |
93 | ///
94 | /// 访问匿名类型成员
95 | ///
96 | ///
97 | ///
98 | protected override Expression VisitNew(NewExpression node)
99 | {
100 | if (node.Members != null)
101 | {
102 | foreach (var item in node.Members)
103 | {
104 | Parameters.Add(item.Name, null);
105 | }
106 | }
107 | return base.VisitNew(node);
108 | }
109 |
110 | ///
111 | /// 访问表达式中的函数调用
112 | ///
113 | ///
114 | ///
115 | ///
116 | protected Expression VisitMethodCall(MethodCallExpression node,string fieldName)
117 | {
118 | string sqlMethodName = node.Method.Name.ToLower();
119 | string callName = SqlMethodNameCallBack.MethodNameCallback(sqlMethodName);
120 | if (!string.IsNullOrEmpty(callName))
121 | {
122 | parameters.Add(fieldName, new Parameter(callName, callName) { IsMethodType = true });
123 | }
124 | else
125 | throw new NotSupportedException(string.Format("{0}数据库中不支持函数{1}","SqlServer",sqlMethodName));
126 |
127 | return base.VisitMethodCall(node);
128 | }
129 |
130 |
131 | internal Dictionary Parameters
132 | {
133 | get { return parameters; }
134 | }
135 |
136 |
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/IOperatorWhere.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq.Expressions;
3 |
4 | namespace Dapper.Extensions
5 | {
6 | ///
7 | /// 条件执行操作类
8 | ///
9 | ///
10 | public interface IOperatorWhere where TModel : class
11 | {
12 | ///
13 | /// 添加条件语句
14 | ///
15 | ///
16 | ///
17 | IOperatorWhere Where(Expression> whereExp);
18 | ///
19 | /// 执行表达式
20 | ///
21 | bool Go();
22 |
23 | ///
24 | /// 调试用的SQL语句
25 | ///
26 | string SQL { get; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/OperatorWhereObject.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.Linq.Expressions;
5 | using System.Text.RegularExpressions;
6 | using Dapper;
7 | using Dapper.Contrib;
8 |
9 | namespace Dapper.Extensions
10 | {
11 | ///
12 | /// 条件执行操作类
13 | ///API采用 .Where(expression).Go()的链式使用方式。
14 | ///
15 | ///
16 | public class OperatorWhereObject : IOperatorWhere where TModel:class
17 | {
18 | internal OperatorWhereObject(IDbConnection p,string sql,List ps )
19 | {
20 | Provider = p;
21 | Parameters = ps;
22 | _sql = sql;
23 | }
24 |
25 | private string _sql;
26 | private List Parameters { set; get; }
27 | private IDbConnection Provider {set; get; }
28 | ///
29 | /// 执行条件执行的表达式语句
30 | ///
31 | public bool Go()
32 | {
33 | if (Provider == null)
34 | return false;
35 |
36 | var dynParms = new DynamicParameters();
37 | Parameters.ForEach(p=> dynParms.Add(p.Name,p.Value));
38 | bool ret = Provider.Execute(this._sql, dynParms) > 0;
39 |
40 | if(Provider.State == ConnectionState.Open) Provider.Close();
41 |
42 | this._sql = null;
43 | return ret;
44 | }
45 |
46 | ///
47 | /// 在没有执行Go之前生成的SQL语句
48 | ///
49 | public string SQL {
50 | get { return _sql; }
51 | }
52 |
53 | ///
54 | /// 添加条件表达式
55 | ///
56 | /// 表达式
57 | /// 条件执行对象
58 | public IOperatorWhere Where(Expression> whereExp)
59 | {
60 | var translate = new SqlTranslateFormater();
61 | string whereSql = translate.Translate(whereExp);
62 | _sql += whereSql;
63 | return this;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/PageCondition.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Dapper.Extensions
8 | {
9 | ///
10 | /// 通用分页输入条件
11 | ///
12 | public class PageCondition
13 | {
14 | ///
15 | /// 通用分页输入条件构造器
16 | ///
17 | /// 表名或SQL语句如1.customer 2.(select * from customer) as t1
18 | /// 当前页数
19 | /// 每页输出的记录数
20 | /// 排序不含'ORDER BY'字符,当@SortType=3时生效,必须指定ASC或DESC,建议在最后加上主键
21 | /// 排序规则(1:单列正序ASC;2:单列倒序DESC;3:多列排序;)
22 | /// 要显示的列名,如果是全部字段则为*
23 | /// 查询条件 不含'WHERE'字符,如t1.Id > 6 5 AND t1.userid > 10000 ,字段应该与表名对应(TableName)如 t1.Id > 6
24 | public PageCondition(string tableName, int pageIndex, int pageSize, string orderField , PageOrderType orderType = PageOrderType.Asc, string fieldNames = "*", string where = null)
25 | {
26 | this.TableName = tableName;
27 | this.Index = pageIndex;
28 | this.Size = pageSize;
29 | this.FieldNames = fieldNames;
30 | this.Where = where;
31 | this.OrderField = orderField;
32 | this.OrderType = orderType;
33 | }
34 |
35 | ///
36 | /// 表名或SQL语句如1.customer 2.(select * from customer) as t1
37 | ///
38 | public string TableName { set; get; }
39 |
40 | ///
41 | /// 要显示的列名,如果是全部字段则为*
42 | ///
43 | public string FieldNames { set; get; }
44 |
45 | ///
46 | /// 查询条件 不含'WHERE'字符,如t1.Id > 6 5 AND t1.userid > 10000 ,字段应该与表名对应(TableName)如 t1.Id > 6
47 | ///
48 | public string Where { set; get; }
49 | ///
50 | /// 排序不含'ORDER BY'字符,当@SortType=3时生效,必须指定ASC或DESC,建议在最后加上主键
51 | ///
52 | public string OrderField { set; get; }
53 | ///
54 | /// 排序规则(1:单列正序ASC;2:单列倒序DESC;3:多列排序;)
55 | ///
56 | public PageOrderType OrderType { set; get; }
57 | ///
58 | /// 当前页数
59 | ///
60 | public int Index { set; get; }
61 | ///
62 | /// 每页输出的记录数
63 | ///
64 | public int Size { set; get; }
65 |
66 | }
67 |
68 | ///
69 | /// 1:单列正序ASC;
70 | /// 2:单列倒序DESC;
71 | /// 3:多列排序;
72 | ///
73 | public enum PageOrderType
74 | {
75 | Asc = 1,
76 | Desc = 2,
77 | Muti =3
78 | }
79 |
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/PageView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Dapper.Extensions
8 | {
9 | ///
10 | /// 数据分页模型
11 | ///
12 | /// 返回的分页数据
13 | public class PageView where TModel : class
14 | {
15 | public PageView(IEnumerable data, int count)
16 | {
17 | this.Data = data;
18 | this.Count = count;
19 | }
20 |
21 | ///
22 | /// 分页数据
23 | ///
24 | public IEnumerable Data { set; get; }
25 |
26 | ///
27 | /// 要分页数据源的总条数
28 | ///
29 | public int Count { set; get; }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/Parameter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 |
4 | namespace Dapper.Extensions
5 | {
6 | ///
7 | /// new 表达式对象中的SQL语句参数,
8 | ///
9 | internal class Parameter
10 | {
11 | public string Name { get; set; }
12 | public object Value { get; set; }
13 |
14 | public bool IsMethodType { set; get; }
15 |
16 | public Parameter() { }
17 |
18 | public Parameter(string name, object value)
19 | {
20 | Name = name;
21 | if(value != null)
22 | Value = value;
23 | }
24 |
25 | public override string ToString()
26 | {
27 | return String.Format(" {0}={1}", Name, Value);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Dapper.Extensions/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("Dapper.Extensions")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("f892188e-c751-4bb2-91ba-75b27236c9cd")]
20 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/SQLMethod.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Dapper.Extensions
4 | {
5 | ///
6 | /// SQL中支持的函数
7 | ///
8 | public class SQLMethod
9 | {
10 | ///
11 | /// 服务器当前时间
12 | ///
13 | ///
14 | static public DateTime GetDate()
15 | {
16 | return new DateTime();
17 | }
18 | ///
19 | /// 字段为空
20 | ///
21 | ///
22 | ///
23 | public static bool IsNull(object obj)
24 | {
25 | return obj == null;
26 | }
27 | ///
28 | /// 字段不为空
29 | ///
30 | ///
31 | ///
32 | public static bool IsNotNull(object obj)
33 | {
34 | return obj != null;
35 | }
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/SqlMapperExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 | using System.Collections;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Reflection;
9 | using Dapper.Contrib.Extensions;
10 |
11 | namespace Dapper.Extensions
12 | {
13 | using Dapper;
14 | using Dapper.Contrib;
15 | using System.Linq.Expressions;
16 | ///
17 | /// Dapper扩展类,扩展支持单表的where语句生成
18 | ///
19 | public static partial class SqlMapperExtensions
20 | {
21 | private static string GetTableName(Type entityType)
22 | {
23 | string tableName = string.Empty;
24 | var attrs = entityType.GetTypeInfo().GetCustomAttributes(typeof(TableAttribute), true).ToArray();
25 | if (attrs != null && attrs.Length > 0)
26 | tableName = ((TableAttribute)attrs[0]).Name;
27 | else
28 | throw new NotSupportedException("实体类上没有TableAttribute特性!");
29 |
30 | return tableName;
31 |
32 | }
33 |
34 |
35 | internal static string CreateQuerySQL(Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
36 | {
37 | string fieldNames = "*";
38 | if (fieldExp != null)
39 | {
40 | FieldsFormater format = new FieldsFormater();
41 | format.Visit(fieldExp);
42 | if (format.Parameters.Count > 0)
43 | {
44 | fieldNames = string.Join(",", format.Parameters.Select(x => x.Key));
45 | }
46 | }
47 |
48 | var translate = new SqlTranslateFormater();
49 | string sqlWhere = translate.Translate(whereExp);
50 |
51 | if (sort != null && sort.Count > 0)
52 | {
53 | sqlWhere += $" Order By {sort}";
54 | }
55 |
56 | string tableName = GetTableName(typeof(T));
57 |
58 | StringBuilder sqlBuilder = new StringBuilder($"select {fieldNames} from {tableName} where ");
59 | sqlBuilder.Append(sqlWhere);
60 | return sqlBuilder.ToString();
61 | }
62 |
63 |
64 | internal static string CreateQuerySQLWithActive(Expression> expression, Expression> fieldExp = null, DapperSort sort = null) where T : class
65 | {
66 | string fieldNames = "*";
67 | if (fieldExp != null)
68 | {
69 | FieldsFormater format = new FieldsFormater();
70 | format.Visit(fieldExp);
71 | if (format.Parameters.Count > 0)
72 | {
73 | fieldNames = string.Join(",", format.Parameters.Select(x => x.Key));
74 | }
75 | }
76 |
77 | var translate = new SqlTranslateFormater();
78 | string sqlWhere = translate.Translate(expression);
79 |
80 | if (sort != null && sort.Count > 0)
81 | {
82 | sqlWhere += $" Order By {sort}";
83 | }
84 |
85 | string tableName = GetTableName(typeof(T));
86 |
87 | StringBuilder sqlBuilder = new StringBuilder($"select {fieldNames} from {tableName} where IsActive=1 AND ");
88 | sqlBuilder.Append(sqlWhere);
89 | return sqlBuilder.ToString();
90 | }
91 |
92 | ///
93 | /// 查找一条数据,并且IsActive=1
94 | ///
95 | /// 表名
96 | /// 数据库连接
97 | /// where表达式
98 | /// 一条实体记录
99 | public static T GetEntityForIsActive(this IDbConnection connection, Expression> expression) where T : class
100 | {
101 | return connection.QueryFirstOrDefault(CreateQuerySQLWithActive(expression));
102 | }
103 |
104 |
105 | ///
106 | /// 同步查找一条数据
107 | ///
108 | /// 表名
109 | /// 数据库连接
110 | /// where表达式
111 | /// 指定查询字段
112 | ///
113 | /// 一条实体记录
114 | public static T Get(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
115 | {
116 | return connection.QueryFirstOrDefault(CreateQuerySQL(whereExp, fieldExp, sort));
117 | }
118 |
119 | ///
120 | /// 异步查找一条数据
121 | ///
122 | /// 表名
123 | /// 数据库连接
124 | /// where表达式
125 | /// 指定查询字段
126 | ///
127 | /// 一条实体记录
128 | public static Task GetAsync(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null)
129 | where T : class
130 | {
131 | return connection.QueryFirstAsync(CreateQuerySQL(whereExp, fieldExp, sort));
132 | }
133 |
134 |
135 | ///
136 | /// 查找数据集合,并且IsActive=1
137 | ///
138 | /// 表名
139 | /// 数据库连接
140 | /// where表达式
141 | /// 指定查询字段
142 | ///
143 | /// 实体记录集合
144 | public static IEnumerable GetAllForIsActive(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
145 | {
146 | return connection.Query(CreateQuerySQLWithActive(whereExp, fieldExp, sort));
147 | }
148 |
149 |
150 | ///
151 | /// 同步查找数据数据集合
152 | ///
153 | /// 表名
154 | /// 数据库连接
155 | /// where表达式
156 | /// 指定查询字段
157 | ///
158 | /// 实体记录集合
159 | public static IEnumerable GetAll(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
160 | {
161 | return connection.Query(CreateQuerySQL(whereExp, fieldExp, sort));
162 | }
163 |
164 | ///
165 | /// 异步查找数据数据集合
166 | ///
167 | /// 表名
168 | /// 数据库连接
169 | /// where表达式
170 | /// 指定查询字段
171 | ///
172 | /// 实体记录集合
173 | public static Task> GetAllAsync(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null)
174 | where T : class
175 | {
176 | return connection.QueryAsync(CreateQuerySQL(whereExp, fieldExp, sort));
177 | }
178 |
179 |
180 | ///
181 | /// 立即执行更新语句,API采用 Update({new entity expression}).Where(expression).Go()的链式使用方式
182 | ///
183 | /// 模型名称
184 | ///
185 | /// 更新对象表达式,表示要更新的列信息
186 | /// 将返回一个操作接口,此接口会有一个Where方法和Go方法,Where表示要添加条件,Go则表示立即执行语句。
187 | /// session.Update(u => new AdminUser1 {ID = "5", NameA = "maxzhang"}).Where(p => p.Age > 5).Go
188 | public static IOperatorWhere Update(this IDbConnection connection, Expression> objExp) where TModel : class
189 | {
190 | string tableName = GetTableName(typeof(TModel));
191 |
192 | FieldsFormater format = new FieldsFormater();
193 | format.Visit(objExp);
194 | string paramterNameAndValues = string.Join(",", format.Parameters.Select(kv => kv.Key + "=" + kv.Value.Name));
195 |
196 | string template = string.Format("Update {0} SET {1} Where ", tableName, paramterNameAndValues);
197 | var ps = format.Parameters.Values.Where(p => p.IsMethodType == false).ToList();
198 |
199 | return new OperatorWhereObject(connection, template, ps);
200 | }
201 |
202 | ///
203 | /// 逻辑删除表对应的一条数据记录
204 | ///
205 | /// 表实体
206 | /// 数据库连接
207 | /// 记录ID
208 | /// 是否逻辑删除
209 | /// 是否逻辑删除成功
210 | public static bool SetActive(this IDbConnection connection, dynamic id, bool isActive = false) where TModel : class
211 | {
212 | var modelType = typeof(TModel);
213 | var keyPropertyInfo = modelType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Count() > 0);
214 | var IsActivePropertyInfo = modelType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(ActiveAttribute), true).Count() > 0);
215 | if (IsActivePropertyInfo == null)
216 | throw new NotSupportedException("实体类没有定义Active特性!");
217 |
218 | string tableName = GetTableName(typeof(TModel));
219 | string template = string.Format("Update {0} SET IsActive=@IsActive Where {1}=@Id", tableName, keyPropertyInfo.Name);
220 | var dynParms = new DynamicParameters();
221 | dynParms.Add("@IsActive", isActive);
222 | dynParms.Add("@Id", id);
223 |
224 | bool ret = connection.Execute(template, dynParms) > 0;
225 | return ret;
226 | }
227 |
228 | ///
229 | /// 逻辑删除表实体对应的一条数据记录
230 | ///
231 | /// 表实体
232 | /// 数据库连接
233 | /// 表实体对象
234 | /// 是否逻辑删除成功
235 | public static bool SetActive(this IDbConnection connection, TModel model) where TModel : class
236 | {
237 | var modelType = typeof(TModel);
238 | var keyPropertyInfo = modelType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Count() > 0);
239 | var IsActivePropertyInfo = modelType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(ActiveAttribute), true).Count() > 0);
240 |
241 | if (keyPropertyInfo == null)
242 | throw new NotSupportedException("实体类没有定义主键(Key)特性!");
243 |
244 | if (IsActivePropertyInfo == null)
245 | throw new NotSupportedException("实体类没有定义逻辑删除(Active)特性!");
246 |
247 | //取得表实体对象的值 id and isactive field
248 | object id = keyPropertyInfo.GetValue(model, null);
249 | object isActive = IsActivePropertyInfo.GetValue(model, null);
250 |
251 | string tableName = GetTableName(typeof(TModel));
252 | //execute sql
253 | string template = string.Format("Update {0} SET IsActive=@IsActive Where {1}=@Id", tableName, keyPropertyInfo.Name);
254 | var dynParms = new DynamicParameters();
255 | dynParms.Add("@IsActive", isActive);
256 | dynParms.Add("@Id", id);
257 |
258 | bool ret = connection.Execute(template, dynParms) > 0;
259 | return ret;
260 | }
261 |
262 |
263 | ///
264 | /// 查找一条数据,并且IsActive=1
265 | ///
266 | /// 表名
267 | /// 数据库连接
268 | /// 表记录ID
269 | ///
270 | /// 一条实体记录
271 | public static TModel GetIsActive(this IDbConnection connection, dynamic id, DapperSort sort = null)
272 | {
273 | var modelType = typeof(TModel);
274 | var tableName = GetTableName(modelType);
275 | var keyPropertyInfo = modelType.GetProperties().FirstOrDefault(p => p.GetCustomAttributes(typeof(KeyAttribute), true).Count() > 0);
276 | if (keyPropertyInfo == null)
277 | throw new NotSupportedException("实体类没有定义主键(Key)特性!");
278 |
279 | string template = $"Select * from {tableName} Where {keyPropertyInfo.Name}=@Id AND IsActive=@IsActive";
280 | if (sort != null && sort.Count > 0)
281 | {
282 | template += string.Format(" Order by {0} ", sort);
283 | }
284 | var dynParms = new DynamicParameters();
285 | dynParms.Add("@IsActive", 1);
286 | dynParms.Add("@Id", id);
287 | return connection.QueryFirstOrDefault(template, dynParms);
288 |
289 | }
290 |
291 | ///
292 | /// 查找数据集合,并且IsActive=1
293 | ///
294 | /// 表名
295 | /// 数据库连接
296 | ///
297 | /// 实体记录集合
298 | public static IEnumerable GetAllIsActive(this IDbConnection connection, DapperSort sort)
299 | {
300 | var modelType = typeof(TModel);
301 | var tableName = GetTableName(modelType);
302 | string template = $"Select * from {tableName} Where IsActive=@IsActive";
303 | if (sort != null && sort.Count > 0)
304 | {
305 | template += string.Format(" Order by {0} ", sort);
306 | }
307 | var dynParms = new DynamicParameters();
308 | dynParms.Add("@IsActive", 1);
309 | return connection.Query(template, dynParms);
310 | }
311 |
312 |
313 | public static PageView GetPager(this IDbConnection connection, PageCondition condition) where TModel : class
314 | {
315 | if (condition == null) throw new ArgumentNullException("condition");
316 |
317 | var dps = new DynamicParameters();
318 | dps.Add("@TableName", condition.TableName);
319 | dps.Add("@FieldNames", condition.FieldNames);
320 |
321 | if (!string.IsNullOrEmpty(condition.Where))
322 | dps.Add("@WhereString", condition.Where);
323 |
324 | dps.Add("@OrderField", condition.OrderField);
325 | dps.Add("@OrderType", Convert.ToInt32(condition.OrderType));
326 |
327 | dps.Add("@PageIndex", condition.Index);
328 | dps.Add("@PageSize", condition.Size);
329 |
330 | PageView pageModel = null;
331 |
332 |
333 | using (var muti = connection.QueryMultiple("Proc_Common_PagerHelper", dps))
334 | {
335 | int count = muti.ReadSingle();
336 | var data = muti.Read();
337 | pageModel = new PageView(data, count);
338 | }
339 |
340 | return pageModel;
341 | }
342 |
343 | ///
344 | /// 立即执行更新语句,API采用 Update(new {ID = "5" NameA = "imyundong"}).Where(expression).Go()的链式使用方式
345 | ///
346 | /// 模型名称
347 | ///
348 | /// 匿名对象或实体对象
349 | /// session.Update(new {ID = "5", NameA = "imyundong"}).Where(p => p.Age > 5).Go
350 | /// session.Update(new {entity.ID, entity.NameA}).Where(p => p.Age > 5).Go
351 | /// session.Update(entity).Where(p => p.Age > 5).Go
352 | ///
353 | public static IOperatorWhere Update(this IDbConnection connection, object param)
354 | where TModel : class
355 | {
356 | string tableName = GetTableName(typeof(TModel));
357 | List ps = new List();
358 |
359 |
360 | IDictionary filesDic = GetObjectValues(param);
361 | List setSql = new List();
362 | foreach (KeyValuePair f in filesDic)
363 | {
364 | setSql.Add(string.Format("{0}=@{0}", f.Key));
365 | ps.Add(new Parameter()
366 | {
367 | IsMethodType = false,
368 | Name = "@" + f.Key,
369 | Value = f.Value
370 | });
371 | }
372 |
373 | string paramterNameAndValues = string.Join(",", setSql);
374 | string template = string.Format("Update {0} SET {1} Where ", tableName, paramterNameAndValues);
375 |
376 | return new OperatorWhereObject(connection, template, ps);
377 | }
378 |
379 | ///
380 | /// 查询数据
381 | ///
382 | ///
383 | ///
384 | /// 查询条件
385 | /// 指定查询字段
386 | /// 排序对象
387 | ///
388 | public static IEnumerable Query(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
389 | {
390 | return connection.Query(CreateQuerySQL(whereExp, fieldExp, sort));
391 | }
392 |
393 | ///
394 | /// 异步查询数据
395 | ///
396 | ///
397 | ///
398 | /// 查询条件
399 | /// 指定查询字段
400 | /// 排序对象
401 | ///
402 | public static Task> QueryAsync(this IDbConnection connection, Expression> whereExp, Expression> fieldExp = null, DapperSort sort = null) where T : class
403 | {
404 | return connection.QueryAsync(CreateQuerySQL(whereExp, fieldExp, sort));
405 | }
406 |
407 | ///
408 | /// 数据是否存在
409 | ///
410 | ///
411 | ///
412 | /// 查询条件
413 | /// 是否逻辑删除状态,默认否
414 | ///
415 | public static bool Exist(this IDbConnection connection, Expression> expression, bool isActive = false)
416 | {
417 | Type type = typeof(TModel);
418 | string tableName = GetTableName(type);
419 |
420 | var translate = new SqlTranslateFormater();
421 | string sqlWhere = translate.Translate(expression);
422 |
423 | StringBuilder sqlBuilder = new StringBuilder($"select 1 from {tableName} where ");
424 | if (isActive)
425 | {
426 | sqlBuilder.Append(" IsActive=1 AND ");
427 | }
428 | sqlBuilder.Append(sqlWhere);
429 |
430 | return connection.ExecuteScalar(sqlBuilder.ToString()) > 0;
431 | }
432 |
433 | ///
434 | /// 反射获取匿名类型或实体的属性键和值
435 | ///
436 | ///
437 | ///
438 | ///
439 | public static IDictionary GetObjectValues(object obj, bool filterComputed = true)
440 | {
441 | IDictionary result = new Dictionary();
442 | if (obj == null)
443 | {
444 | return result;
445 | }
446 |
447 | foreach (var propertyInfo in obj.GetType().GetProperties())
448 | {
449 | string name = propertyInfo.Name;
450 | object value = propertyInfo.GetValue(obj, null);
451 | if (filterComputed)
452 | {
453 | // 忽略标记Computed特性的属性
454 | var computedAttr = propertyInfo
455 | .GetCustomAttributes(false)
456 | .SingleOrDefault(attr => attr.GetType().Name == "ComputedAttribute")
457 | as dynamic;
458 | if (computedAttr == null)
459 | {
460 | result[name] = value;
461 | }
462 | }
463 | else
464 | {
465 | result[name] = value;
466 | }
467 | }
468 |
469 |
470 | return result;
471 | }
472 | }
473 | }
--------------------------------------------------------------------------------
/src/Dapper.Extensions/SqlMethodNameCallBack.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Dapper.Extensions
8 | {
9 | ///
10 | /// SQL语句中的函数映射
11 | ///
12 | public class SqlMethodNameCallBack
13 | {
14 | ///
15 | /// 返回在SQLMethod类中定义函数在SQLServer中调用名称
16 | ///
17 | /// SQLMethod类的静态函数名
18 | /// SQLServer中的函数名称
19 | public static string MethodNameCallback(string methodName)
20 | {
21 | string retName = string.Empty;
22 | switch (methodName)
23 | {
24 | case "getdate":
25 | retName = "GETDATE()";
26 | break;
27 |
28 | default:
29 | break;
30 | }
31 |
32 | return retName;
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Dapper.Extensions/SqlTranslateFormater.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Text;
6 | using System.Collections.Generic;
7 | using System.Collections.Concurrent;
8 | using System.Reflection;
9 |
10 | namespace Dapper.Extensions
11 | {
12 | ///
13 | /// Maker:张磊
14 | /// 解析整个Linq成SQL语句的入口
15 | ///
16 | public class SqlTranslateFormater : ExpressionVisitor
17 | {
18 | ///
19 | ///
20 | ///
21 | private ConcurrentDictionary Ass = new ConcurrentDictionary();
22 | ///
23 | /// sql语句变量
24 | ///
25 | StringBuilder sb = null;
26 | StringBuilder ordby = null;
27 | ///
28 | /// 入口
29 | ///
30 | ///
31 | ///
32 | public string Translate(Expression expr)
33 | {
34 | sb = new StringBuilder();
35 | ordby = new StringBuilder();
36 |
37 | this.Visit(expr);
38 | return sb.ToString();
39 | }
40 |
41 | bool isleft = true;
42 |
43 | ///
44 | /// 访问二元操作符, 如 a >= b, 表达式的left 为a , right为b , 表达式的NodeType为 操作符
45 | ///
46 | ///
47 | ///
48 | protected override Expression VisitBinary(BinaryExpression b)
49 | {
50 | isleft = true;
51 |
52 | this.VisitBinaryWithParent(b, b.Left);
53 |
54 | switch (b.NodeType)
55 | {
56 | case ExpressionType.AndAlso:
57 | sb.Append(" AND ");
58 | break;
59 | case ExpressionType.OrElse:
60 | sb.Append(" OR ");
61 | break;
62 | case ExpressionType.GreaterThan:
63 | sb.Append(" > ");
64 | break;
65 | case ExpressionType.LessThan:
66 | sb.Append(" < ");
67 | break;
68 | case ExpressionType.Equal:
69 | sb.Append(" = ");
70 | break;
71 | case ExpressionType.LessThanOrEqual:
72 | sb.Append(" <= ");
73 | break;
74 | case ExpressionType.GreaterThanOrEqual:
75 | sb.Append(" >= ");
76 | break;
77 | case ExpressionType.NotEqual:
78 | sb.Append(" <> ");
79 | break;
80 | }
81 |
82 | isleft = false;
83 |
84 | this.VisitBinaryWithParent(b, b.Right);
85 |
86 |
87 | return b;
88 | }
89 |
90 | //访问父节点,用于优先级计算
91 | private void VisitBinaryWithParent(Expression parent, Expression node)
92 | {
93 | var left = isleft;
94 | if (IsDiffNoteType(parent, node))
95 | sb.Append("(");
96 |
97 | var bnode = node as BinaryExpression;
98 |
99 | if (bnode != null && bnode.Left is BinaryExpression)
100 | this.VisitBinaryWithParent(node, bnode.Left);
101 | else
102 | {
103 | isleft = true;
104 | if (bnode != null)
105 | this.Visit(bnode.Left);
106 | else
107 | this.Visit(node);
108 | isleft = left;
109 | }
110 |
111 | switch (node.NodeType)
112 | {
113 | case ExpressionType.AndAlso:
114 | sb.Append(" AND ");
115 | break;
116 | case ExpressionType.OrElse:
117 | sb.Append(" OR ");
118 | break;
119 | case ExpressionType.GreaterThan:
120 | sb.Append(" > ");
121 | break;
122 | case ExpressionType.LessThan:
123 | sb.Append(" < ");
124 | break;
125 | case ExpressionType.Equal:
126 | sb.Append(" = ");
127 | break;
128 | case ExpressionType.LessThanOrEqual:
129 | sb.Append(" <= ");
130 | break;
131 | case ExpressionType.GreaterThanOrEqual:
132 | sb.Append(" >= ");
133 | break;
134 | case ExpressionType.NotEqual:
135 | sb.Append(" <> ");
136 | break;
137 | default:
138 | return;
139 | }
140 |
141 | if (bnode != null && bnode.Right is BinaryExpression)
142 | this.VisitBinaryWithParent(node, bnode.Right);
143 | else
144 | {
145 | isleft = false;
146 | if (bnode != null)
147 | this.Visit(bnode.Right);
148 | else
149 | this.Visit(node);
150 | isleft = left;
151 | }
152 |
153 | if (IsDiffNoteType(parent, node))
154 | sb.Append(")");
155 | }
156 |
157 | //得到表达式中c.ID中的c
158 | private void GetParentMemberName(Expression node)
159 | {
160 | if (node.NodeType == ExpressionType.MemberAccess)
161 | {
162 | var memberEx = node as MemberExpression;
163 | GetParentMemberName(memberEx.Expression);
164 | sb.Append(memberEx.Member.Name);
165 | sb.Append(".");
166 | }
167 | }
168 |
169 | //看上一个节点和下一个是不是一样的操作符
170 | private bool IsDiffNoteType(Expression parent, Expression children)
171 | {
172 | if (IsOpertaorType(parent) && IsOpertaorType(children))
173 | {
174 | if (parent.NodeType == children.NodeType)
175 | return false;
176 | else
177 | return true;
178 | }
179 | else
180 | {
181 |
182 | return false;
183 | }
184 |
185 | }
186 |
187 | bool IsOpertaorType(Expression node)
188 | {
189 | switch (node.NodeType)
190 | {
191 | case ExpressionType.AndAlso:
192 | case ExpressionType.OrElse:
193 | return true;
194 | default:
195 | return false;
196 | }
197 | }
198 |
199 |
200 |
201 |
202 | ///
203 | /// 访问成员
204 | ///
205 | ///
206 | ///
207 | protected override Expression VisitMember(MemberExpression node)
208 | {
209 | if (node.Expression != null && (node.Expression.NodeType == ExpressionType.Parameter || node.Expression.NodeType == ExpressionType.MemberAccess) && isleft)
210 | {
211 | bool isAsName = false;
212 | var pse = node.Expression as ParameterExpression;
213 | if (pse != null && pse.Type == node.Member.DeclaringType)
214 | {
215 | if (!Ass.Keys.Contains(pse.Type))
216 | Ass.TryAdd(pse.Type, pse.Name);
217 | isAsName = true;
218 | }
219 | string ts;
220 | if (node.Member.DeclaringType != null && (!isAsName && !Ass.TryGetValue(node.Member.DeclaringType, out ts)))
221 | GetParentMemberName(node.Expression);
222 |
223 | var fieldName = node.Member.Name;
224 |
225 | string tn = string.Empty;
226 | //成员表达式的别名 如 c.Name
227 | //if (Ass.TryGetValue(node.Member.DeclaringType,out tn))
228 | //{
229 | // sb.Append(tn);
230 | // sb.Append(".");
231 | //}
232 |
233 | sb.Append(fieldName);
234 | return node;
235 | }
236 | else
237 | {
238 | LambdaExpression lambda = Expression.Lambda(node);
239 | var fn = lambda.Compile();
240 | this.Visit(Expression.Constant(fn.DynamicInvoke(null), node.Type));
241 |
242 | }
243 |
244 | return node;
245 | }
246 | ///
247 | /// 访问常量
248 | ///
249 | ///
250 | ///
251 | protected override Expression VisitConstant(ConstantExpression c)
252 | {
253 | IQueryable q = c.Value as IQueryable;
254 | if (q != null)
255 | {
256 |
257 | var tableName = q.ElementType.Name;
258 |
259 | sb.Append(tableName);
260 |
261 | sb.Append(" ");
262 | if (Ass.Keys.Count > 0)
263 | sb.Append(Ass[q.ElementType]);
264 | else
265 | sb.Append("T");
266 | }
267 | else if (c.Value == null)
268 | {
269 | sb.Append("NULL");
270 | }
271 | else
272 | {
273 | switch (Type.GetTypeCode(c.Value.GetType()))
274 | {
275 | case TypeCode.Boolean:
276 | sb.Append(((bool)c.Value) ? 1 : 0);
277 | break;
278 | case TypeCode.DateTime:
279 | string dtfs = "'{0}'";
280 | sb.AppendFormat(dtfs, c.Value);
281 | break;
282 | case TypeCode.String:
283 | sb.Append("'");
284 | sb.Append(c.Value);
285 | sb.Append("'");
286 | break;
287 | case TypeCode.Object:
288 | #if COREFX
289 | if (c.Type.GetTypeInfo().GetInterface("IEnumerable", false) != null)
290 | #else
291 | if (c.Type.GetInterface("IEnumerable", false) != null)
292 | #endif
293 | {
294 | List