Skip to content

Commit 62b3c91

Browse files
author
Nick Craver
committed
Merge remote-tracking branch 'origin/main' into pr/1254
2 parents dac717d + dffb443 commit 62b3c91

File tree

192 files changed

+4541
-2999
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+4541
-2999
lines changed

.github/workflows/main.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Main Build
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
paths:
9+
- '*'
10+
- '!/docs/*' # Don't run workflow when files are only in the /docs directory
11+
12+
jobs:
13+
vm-job:
14+
name: Ubuntu
15+
runs-on: ubuntu-latest
16+
services:
17+
postgres:
18+
image: postgres
19+
ports:
20+
- 5432/tcp
21+
env:
22+
POSTGRES_USER: postgres
23+
POSTGRES_PASSWORD: postgres
24+
POSTGRES_DB: test
25+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
26+
sqlserver:
27+
image: mcr.microsoft.com/mssql/server:2019-latest
28+
ports:
29+
- 1433/tcp
30+
env:
31+
ACCEPT_EULA: Y
32+
SA_PASSWORD: "Password."
33+
mysql:
34+
image: mysql
35+
ports:
36+
- 3306/tcp
37+
env:
38+
MYSQL_ROOT_PASSWORD: root
39+
MYSQL_DATABASE: test
40+
steps:
41+
- name: Checkout code
42+
uses: actions/checkout@v1
43+
- name: .NET Build
44+
run: dotnet build Build.csproj -c Release /p:CI=true
45+
- name: Dapper Tests
46+
run: dotnet test tests/Dapper.Tests/Dapper.Tests.csproj -c Release --logger GitHubActions /p:CI=true
47+
env:
48+
MySqlConnectionString: Server=localhost;Port=${{ job.services.mysql.ports[3306] }};Uid=root;Pwd=root;Database=test;Allow User Variables=true
49+
OLEDBConnectionString: Provider=SQLOLEDB;Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
50+
PostgesConnectionString: Server=localhost;Port=${{ job.services.postgres.ports[5432] }};Database=test;User Id=postgres;Password=postgres;
51+
SqlServerConnectionString: Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
52+
- name: Dapper.Contrib Tests
53+
run: dotnet test tests/Dapper.Tests.Contrib/Dapper.Tests.Contrib.csproj -c Release --logger GitHubActions /p:CI=true
54+
env:
55+
MySqlConnectionString: Server=localhost;Port=${{ job.services.mysql.ports[3306] }};Uid=root;Pwd=root;Database=test;Allow User Variables=true
56+
OLEDBConnectionString: Provider=SQLOLEDB;Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
57+
PostgesConnectionString: Server=localhost;Port=${{ job.services.postgres.ports[5432] }};Database=test;User Id=postgres;Password=postgres;
58+
SqlServerConnectionString: Server=tcp:localhost,${{ job.services.sqlserver.ports[1433] }};Database=tempdb;User Id=sa;Password=Password.;
59+
- name: .NET Lib Pack
60+
run: dotnet pack Build.csproj --no-build -c Release /p:PackageOutputPath=%CD%\.nupkgs /p:CI=true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ TestResults/
1919
Dapper.Tests/*.sdf
2020
Dapper.Tests/SqlServerTypes/
2121
.dotnet/*
22-
BenchmarkDotNet.Artifacts/
22+
BenchmarkDotNet.Artifacts/
23+
.idea/

Build.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project Sdk="Microsoft.Build.Traversal/2.0.24">
2+
<ItemGroup>
3+
<ProjectReference Include="benchmarks/**/*.csproj" />
4+
<ProjectReference Include="*/*.csproj" />
5+
<ProjectReference Include="tests/**/*.csproj" />
6+
</ItemGroup>
7+
</Project>

Dapper.Contrib/Dapper.Contrib.csproj

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,22 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<AssemblyName>Dapper.Contrib</AssemblyName>
4-
<PackageTags>orm;sql;micro-orm;dapper</PackageTags>
54
<Title>Dapper.Contrib</Title>
5+
<PackageTags>orm;sql;micro-orm;dapper</PackageTags>
66
<Description>The official collection of get, insert, update and delete helpers for Dapper.net. Also handles lists of entities and optional "dirty" tracking of interface-based entities.</Description>
77
<Authors>Sam Saffron;Johan Danforth</Authors>
8-
<TargetFrameworks>net451;netstandard1.3;netstandard2.0</TargetFrameworks>
9-
<!-- TODO: Docs -->
8+
<TargetFrameworks>net461;netstandard2.0;net5.0</TargetFrameworks>
109
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
10+
<NoWarn>$(NoWarn);CA1050</NoWarn>
1111
</PropertyGroup>
12-
<ItemGroup>
13-
<Compile Include="..\Dapper\TypeExtensions.cs" />
14-
</ItemGroup>
1512
<ItemGroup>
1613
<ProjectReference Include="..\Dapper\Dapper.csproj" />
1714
</ItemGroup>
18-
<ItemGroup Condition="'$(TargetFramework)' == 'net451'">
19-
<Reference Include="System.Data" />
20-
<Reference Include="System.Data.Linq" />
21-
<Reference Include="System" />
22-
<Reference Include="Microsoft.CSharp" />
23-
</ItemGroup>
24-
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' OR '$(TargetFramework)' == 'netstandard2.0'">
25-
<PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
26-
</ItemGroup>
2715
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
28-
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
16+
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
17+
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
18+
</ItemGroup>
19+
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
20+
<Reference Include="Microsoft.CSharp" />
2921
</ItemGroup>
3022
</Project>

Dapper.Contrib/Readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Special Attributes
118118
----------
119119
Dapper.Contrib makes use of some optional attributes:
120120

121-
* `[Table("Tablename")]` - use another table name instead of the name of the class
121+
* `[Table("Tablename")]` - use another table name instead of the (by default pluralized) name of the class
122122

123123
```csharp
124124
[Table ("emps")]

Dapper.Contrib/SqlMapperExtensions.Async.cs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace Dapper.Contrib.Extensions
1212
public static partial class SqlMapperExtensions
1313
{
1414
/// <summary>
15-
/// Returns a single entity by a single id from table "Ts" asynchronously using .NET 4.5 Task. T must be of interface type.
15+
/// Returns a single entity by a single id from table "Ts" asynchronously using Task. T must be of interface type.
1616
/// Id must be marked with [Key] attribute.
1717
/// Created entity is tracked/intercepted for changes and used by the Update() extension.
1818
/// </summary>
@@ -34,24 +34,24 @@ public static async Task<T> GetAsync<T>(this IDbConnection connection, dynamic i
3434
GetQueries[type.TypeHandle] = sql;
3535
}
3636

37-
var dynParms = new DynamicParameters();
38-
dynParms.Add("@id", id);
37+
var dynParams = new DynamicParameters();
38+
dynParams.Add("@id", id);
3939

40-
if (!type.IsInterface())
41-
return (await connection.QueryAsync<T>(sql, dynParms, transaction, commandTimeout).ConfigureAwait(false)).FirstOrDefault();
40+
if (!type.IsInterface)
41+
return (await connection.QueryAsync<T>(sql, dynParams, transaction, commandTimeout).ConfigureAwait(false)).FirstOrDefault();
4242

43-
var res = (await connection.QueryAsync<dynamic>(sql, dynParms).ConfigureAwait(false)).FirstOrDefault() as IDictionary<string, object>;
44-
45-
if (res == null)
43+
if (!((await connection.QueryAsync<dynamic>(sql, dynParams).ConfigureAwait(false)).FirstOrDefault() is IDictionary<string, object> res))
44+
{
4645
return null;
46+
}
4747

4848
var obj = ProxyGenerator.GetInterfaceProxy<T>();
4949

5050
foreach (var property in TypePropertiesCache(type))
5151
{
5252
var val = res[property.Name];
5353
if (val == null) continue;
54-
if (property.PropertyType.IsGenericType() && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
54+
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
5555
{
5656
var genericType = Nullable.GetUnderlyingType(property.PropertyType);
5757
if (genericType != null) property.SetValue(obj, Convert.ChangeType(val, genericType), null);
@@ -68,7 +68,7 @@ public static async Task<T> GetAsync<T>(this IDbConnection connection, dynamic i
6868
}
6969

7070
/// <summary>
71-
/// Returns a list of entites from table "Ts".
71+
/// Returns a list of entities from table "Ts".
7272
/// Id of T must be marked with [Key] attribute.
7373
/// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension
7474
/// for optimal performance.
@@ -92,7 +92,7 @@ public static Task<IEnumerable<T>> GetAllAsync<T>(this IDbConnection connection,
9292
GetQueries[cacheType.TypeHandle] = sql;
9393
}
9494

95-
if (!type.IsInterface())
95+
if (!type.IsInterface)
9696
{
9797
return connection.QueryAsync<T>(sql, null, transaction, commandTimeout);
9898
}
@@ -101,7 +101,7 @@ public static Task<IEnumerable<T>> GetAllAsync<T>(this IDbConnection connection,
101101

102102
private static async Task<IEnumerable<T>> GetAllAsyncImpl<T>(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string sql, Type type) where T : class
103103
{
104-
var result = await connection.QueryAsync(sql).ConfigureAwait(false);
104+
var result = await connection.QueryAsync(sql, transaction: transaction, commandTimeout: commandTimeout).ConfigureAwait(false);
105105
var list = new List<T>();
106106
foreach (IDictionary<string, object> res in result)
107107
{
@@ -110,7 +110,7 @@ private static async Task<IEnumerable<T>> GetAllAsyncImpl<T>(IDbConnection conne
110110
{
111111
var val = res[property.Name];
112112
if (val == null) continue;
113-
if (property.PropertyType.IsGenericType() && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
113+
if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
114114
{
115115
var genericType = Nullable.GetUnderlyingType(property.PropertyType);
116116
if (genericType != null) property.SetValue(obj, Convert.ChangeType(val, genericType), null);
@@ -127,7 +127,7 @@ private static async Task<IEnumerable<T>> GetAllAsyncImpl<T>(IDbConnection conne
127127
}
128128

129129
/// <summary>
130-
/// Inserts an entity into table "Ts" asynchronously using .NET 4.5 Task and returns identity id.
130+
/// Inserts an entity into table "Ts" asynchronously using Task and returns identity id.
131131
/// </summary>
132132
/// <typeparam name="T">The type being inserted.</typeparam>
133133
/// <param name="connection">Open SqlConnection</param>
@@ -140,19 +140,19 @@ public static Task<int> InsertAsync<T>(this IDbConnection connection, T entityTo
140140
int? commandTimeout = null, ISqlAdapter sqlAdapter = null) where T : class
141141
{
142142
var type = typeof(T);
143-
sqlAdapter = sqlAdapter ?? GetFormatter(connection);
143+
sqlAdapter ??= GetFormatter(connection);
144144

145145
var isList = false;
146146
if (type.IsArray)
147147
{
148148
isList = true;
149149
type = type.GetElementType();
150150
}
151-
else if (type.IsGenericType())
151+
else if (type.IsGenericType)
152152
{
153153
var typeInfo = type.GetTypeInfo();
154154
bool implementsGenericIEnumerableOrIsGenericIEnumerable =
155-
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType() && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
155+
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
156156
typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>);
157157

158158
if (implementsGenericIEnumerableOrIsGenericIEnumerable)
@@ -198,7 +198,7 @@ public static Task<int> InsertAsync<T>(this IDbConnection connection, T entityTo
198198
}
199199

200200
/// <summary>
201-
/// Updates entity in table "Ts" asynchronously using .NET 4.5 Task, checks if the entity is modified if the entity is tracked by the Get() extension.
201+
/// Updates entity in table "Ts" asynchronously using Task, checks if the entity is modified if the entity is tracked by the Get() extension.
202202
/// </summary>
203203
/// <typeparam name="T">Type to be updated</typeparam>
204204
/// <param name="connection">Open SqlConnection</param>
@@ -219,11 +219,11 @@ public static async Task<bool> UpdateAsync<T>(this IDbConnection connection, T e
219219
{
220220
type = type.GetElementType();
221221
}
222-
else if (type.IsGenericType())
222+
else if (type.IsGenericType)
223223
{
224224
var typeInfo = type.GetTypeInfo();
225225
bool implementsGenericIEnumerableOrIsGenericIEnumerable =
226-
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType() && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
226+
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
227227
typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>);
228228

229229
if (implementsGenericIEnumerableOrIsGenericIEnumerable)
@@ -269,7 +269,7 @@ public static async Task<bool> UpdateAsync<T>(this IDbConnection connection, T e
269269
}
270270

271271
/// <summary>
272-
/// Delete entity in table "Ts" asynchronously using .NET 4.5 Task.
272+
/// Delete entity in table "Ts" asynchronously using Task.
273273
/// </summary>
274274
/// <typeparam name="T">Type of entity</typeparam>
275275
/// <param name="connection">Open SqlConnection</param>
@@ -288,11 +288,11 @@ public static async Task<bool> DeleteAsync<T>(this IDbConnection connection, T e
288288
{
289289
type = type.GetElementType();
290290
}
291-
else if (type.IsGenericType())
291+
else if (type.IsGenericType)
292292
{
293293
var typeInfo = type.GetTypeInfo();
294294
bool implementsGenericIEnumerableOrIsGenericIEnumerable =
295-
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType() && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
295+
typeInfo.ImplementedInterfaces.Any(ti => ti.IsGenericType && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)) ||
296296
typeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>);
297297

298298
if (implementsGenericIEnumerableOrIsGenericIEnumerable)
@@ -307,26 +307,26 @@ public static async Task<bool> DeleteAsync<T>(this IDbConnection connection, T e
307307
throw new ArgumentException("Entity must have at least one [Key] or [ExplicitKey] property");
308308

309309
var name = GetTableName(type);
310-
keyProperties.AddRange(explicitKeyProperties);
310+
var allKeyProperties = keyProperties.Concat(explicitKeyProperties).ToList();
311311

312312
var sb = new StringBuilder();
313313
sb.AppendFormat("DELETE FROM {0} WHERE ", name);
314314

315315
var adapter = GetFormatter(connection);
316-
317-
for (var i = 0; i < keyProperties.Count; i++)
316+
317+
for (var i = 0; i < allKeyProperties.Count; i++)
318318
{
319-
var property = keyProperties[i];
319+
var property = allKeyProperties[i];
320320
adapter.AppendColumnNameEqualsValue(sb, property.Name);
321-
if (i < keyProperties.Count - 1)
321+
if (i < allKeyProperties.Count - 1)
322322
sb.Append(" AND ");
323323
}
324324
var deleted = await connection.ExecuteAsync(sb.ToString(), entityToDelete, transaction, commandTimeout).ConfigureAwait(false);
325325
return deleted > 0;
326326
}
327327

328328
/// <summary>
329-
/// Delete all entities in the table related to the type T asynchronously using .NET 4.5 Task.
329+
/// Delete all entities in the table related to the type T asynchronously using Task.
330330
/// </summary>
331331
/// <typeparam name="T">Type of entity</typeparam>
332332
/// <param name="connection">Open SqlConnection</param>
@@ -379,7 +379,7 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
379379
var cmd = $"INSERT INTO {tableName} ({columnList}) values ({parameterList}); SELECT SCOPE_IDENTITY() id";
380380
var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
381381

382-
var first = multi.Read().FirstOrDefault();
382+
var first = await multi.ReadFirstOrDefaultAsync().ConfigureAwait(false);
383383
if (first == null || first.id == null) return 0;
384384

385385
var id = (int)first.id;
@@ -499,7 +499,7 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
499499

500500
var results = await connection.QueryAsync(sb.ToString(), entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
501501

502-
// Return the key by assinging the corresponding property in the object - by product is that it supports compound primary keys
502+
// Return the key by assigning the corresponding property in the object - by product is that it supports compound primary keys
503503
var id = 0;
504504
foreach (var p in propertyInfos)
505505
{
@@ -531,7 +531,7 @@ public async Task<int> InsertAsync(IDbConnection connection, IDbTransaction tran
531531
var cmd = $"INSERT INTO {tableName} ({columnList}) VALUES ({parameterList}); SELECT last_insert_rowid() id";
532532
var multi = await connection.QueryMultipleAsync(cmd, entityToInsert, transaction, commandTimeout).ConfigureAwait(false);
533533

534-
var id = (int)multi.Read().First().id;
534+
var id = (int)(await multi.ReadFirstAsync().ConfigureAwait(false)).id;
535535
var pi = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
536536
if (pi.Length == 0) return id;
537537

0 commit comments

Comments
 (0)