Commit Graph
1422 Commits
Author SHA1 Message Date
Nick Craver 009b4302dd Merge pull request #1560 from wswind/main
Remove an extra right parenthesis in literal replacements demo code.
2020-10-23 16:10:07 -04:00
wswind 9c862af743 Update Readme.md
remove a right parenthesis in literal replacements demo code.
2020-10-19 10:43:13 +08:00
Nick Craver 812b060b57 Merge pull request #1558 from paul42/patch-1
update tests link in readme
2020-10-17 08:56:56 -04:00
Paul.42 a6f99ced92 update tests link in readme 2020-10-16 15:07:42 -07:00
Nick Craver cdc63c747e Merge pull request #1556 from StackExchange/craver/project-reorg1
One of several moves to make this something we can dev on all platforms and build on Actions for v3 onwards.

This leaves the main projects in the root, creating the following:
```
benchmarks\
    Dapper.Tests.Performance
    Directory.Build.props
tests\
    Dapper.Tests
    Dapper.Tests.Contrib
    Directory.Build.props
    Directory.Build.targets
```

Next step is getting `tests\docker-compose.yml` spun up for testing the various providers on GitHub Actions, but I'm having issues with this loaner laptop and the Docker restore from backup being in a screwy state.
2020-10-12 11:31:34 -04:00
Nick Craver 6dd097be41 Fix .sln file 2020-10-12 07:30:07 -04:00
Nick Craver 78ed4b2077 Tests: move into folders
One of several moves to make this something we can dev on all platforms and build on Actions for v3 onwards.
2020-10-11 14:56:35 -04:00
Nick Craver e2ffcdd1a4 Ignore JetBrains files 2020-08-18 21:54:34 -04:00
Nick Craver 97304d053e Merge pull request #1462 from DarkWanderer/patch-1
Add correct feature flag for ClickHouse
2020-07-31 16:45:19 -04:00
Nick Craver 942f91de86 Merge pull request #1507 from imba-tjd/patch-1
Readme: Fix Syntax error:
`Cannot apply indexing with [] to an expression of type 'IEnumerable<dynamic>'`
2020-07-31 16:42:09 -04:00
Nick Craver d2877e0400 Update Readme.md 2020-07-31 16:41:35 -04:00
Dogac Akyıldız e47d819d4e Fix Typo. (#1508) 2020-07-31 16:39:56 -04:00
谭九鼎 cea7a012b0 Fix Syntax error 2020-07-27 13:57:20 +08:00
Nick Craver e723ceed16 master -> main changes 2020-06-20 09:40:54 -04:00
Oleg V. Kozlyuk b17a989950 Add correct feature flag for ClickHouse
Properly indicate array support for ClickHouse connections
ClickHouse: https://clickhouse.tech/
ClickHouse .NET client: https://github.com/DarkWanderer/ClickHouse.Client
2020-05-12 01:12:12 +03:00
Damir Ainullin 4fb1ea29d4 Replace empty array with Array.Empty<T>, add compound assignment, fix of grammar typo (#1459)
Misc cleanup
2020-05-10 06:52:06 -04:00
Damir Ainullin 2bc267f529 Fixes of grammar typos (#1458)
Fixes of grammar typos
2020-05-09 16:00:24 -04:00
Damir Ainullin f4aec37711 Replace sync methods calls with async analogs (#1457)
Replace sync methods calls with async analogs
2020-05-08 18:01:02 -04:00
Damir Ainullin d403fa5b54 Removed excessive casts (#1452)
Removed excessive casts
2020-05-07 07:22:25 -04:00
Nick Craver 3371bf2b7f Normalize deserialization errors for bad data (#1453)
This normalizes all the cases of trying to set null to non-null things and giving a better exception when it happens. Today when a user does something like this:

```cs
conn.QueryFirstOrDefault<int>("Select null;");
```
...we'll get a null ref in the `(T)val;` portion of the deserialization pass. It's not very intuitive as to what's gone wrong. The same is true for value tuples and all `Query*<T>()` methods. However, we handle this in a much friendlier way in the generated type deserializers (already, in master) with a message like:
> Error parsing column 1 (Foo=bar - String)

This gives the type we _actually_ got for the column and the position it was in. This PR improves the case for anything from `Query<int>` to `QueryFirst<int>`, etc. We could be more intuitive _if we passed the expected type in_ (which we don't today via the IL Path), or if we can come up with a generic error message along the lines of "... - use a nullable type (e.g. `int?` instead of `int`) if null is expected.". Or something like that - thoughts?

We're using `DataException` because that's what we're already doing on type deserialization in the default paths. That's the generic exception type that'll always work (it's not always a cast or parsing exception...it could be either)...and since it's already in use, sticking with it here.

Overall changes:
- DRYs up `QueryRowImpl<T>` and `QueryRowAsync<T>` (single row paths) - into `ReadRow<T>`
- DRYs up value setting code between `Query<T>`, `QueryAsync<T>`, `QueryRowImpl<T>`, `QueryRowAsync<T>` - into `GetValue<T>`
- When trying to set a null to a non-nullable type, it'll throw a much better exception.
- Adds tests to ensure these error messages are consistent.

Theoretical breaking change:
- Someone's doing this and catching null ref exceptions or string format exceptions. If that's the case, we'll change their exception expectations here - I think in net we should still do this.

Related to:
- #567
- #1421
- #1440 

### TODO
- [ ] ValueTuple support - these are handled in yet another path and still throw a different casting error. Note: they won't throw a null error because that's a column and we won't set it - unless `.ApplyNullValues` is set in settings.


### Benchmarks:
```ini
BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.208 (2004/?/20H1)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.1.201
  [Host]   : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
  ShortRun : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
```

#### Before (3 runs)
|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 117.4 us | 1.62 us | 2.46 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 119.4 us | 0.58 us | 0.88 us | 1.8750 | 0.8750 |      - |  11.65 KB |
| Dapper |        QueryFirstOrDefault<T> |    Post | 120.7 us | 0.78 us | 1.30 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 125.0 us | 2.62 us | 4.41 us | 2.5000 | 1.0000 | 0.2500 |  11.73 KB |
| Dapper |              'Contrib Get<T>' |    Post | 127.8 us | 3.19 us | 4.82 us | 2.5000 | 1.0000 | 0.2500 |  12.29 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 160.8 us | 1.19 us | 2.28 us | 2.0000 | 1.0000 |      - |  11.77 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 170.6 us | 1.71 us | 2.58 us | 2.0000 | 1.0000 |      - |  11.81 KB |

|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 114.5 us | 1.81 us | 2.73 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |        QueryFirstOrDefault<T> |    Post | 117.9 us | 0.93 us | 1.56 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 121.3 us | 1.52 us | 2.55 us | 2.5000 | 1.0000 | 0.2500 |  11.73 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 122.7 us | 1.09 us | 2.08 us | 2.0000 | 1.0000 |      - |  11.65 KB |
| Dapper |              'Contrib Get<T>' |    Post | 127.9 us | 1.40 us | 2.12 us | 2.5000 | 0.7500 | 0.2500 |  12.29 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 166.9 us | 1.02 us | 1.71 us | 2.0000 | 1.0000 |      - |  11.77 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 170.1 us | 2.19 us | 3.31 us | 2.0000 | 1.0000 |      - |  11.81 KB |

|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 115.5 us | 3.14 us | 4.75 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |        QueryFirstOrDefault<T> |    Post | 121.5 us | 4.29 us | 7.21 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 123.9 us | 2.16 us | 3.27 us | 2.0000 | 1.0000 |      - |  11.65 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 127.0 us | 3.65 us | 5.52 us | 2.3750 | 0.8750 | 0.3750 |  11.73 KB |
| Dapper |              'Contrib Get<T>' |    Post | 130.0 us | 3.18 us | 4.80 us | 2.5000 | 0.7500 | 0.2500 |  12.29 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 166.7 us | 1.39 us | 2.33 us | 2.7500 | 1.0000 | 0.2500 |  11.81 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 170.6 us | 2.18 us | 3.29 us | 2.2500 | 1.0000 | 0.2500 |  11.77 KB |

#### After (3 runs):
|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 113.2 us | 0.45 us | 0.75 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 118.7 us | 1.97 us | 2.98 us | 1.8750 | 0.8750 |      - |  11.72 KB |
| Dapper |        QueryFirstOrDefault<T> |    Post | 119.6 us | 1.12 us | 1.88 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 121.8 us | 4.16 us | 6.28 us | 2.5000 | 1.0000 | 0.2500 |  11.64 KB |
| Dapper |              'Contrib Get<T>' |    Post | 124.0 us | 1.21 us | 2.04 us | 2.0000 | 1.0000 |      - |  12.28 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 162.4 us | 1.95 us | 3.27 us | 2.2500 | 1.0000 | 0.2500 |  11.76 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 173.0 us | 2.68 us | 4.50 us | 2.5000 | 1.0000 | 0.2500 |   11.8 KB |

|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 114.1 us | 1.42 us | 2.15 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |        QueryFirstOrDefault<T> |    Post | 120.4 us | 1.23 us | 1.87 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 121.4 us | 3.90 us | 5.90 us | 1.8750 | 0.8750 |      - |  11.72 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 125.7 us | 1.65 us | 2.50 us | 2.0000 | 1.0000 |      - |  11.64 KB |
| Dapper |              'Contrib Get<T>' |    Post | 132.1 us | 3.01 us | 4.55 us | 2.2500 | 0.7500 |      - |  12.28 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 162.1 us | 2.29 us | 3.85 us | 2.7500 | 1.0000 | 0.2500 |   11.8 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 166.9 us | 2.19 us | 3.31 us | 2.2500 | 1.0000 | 0.2500 |  11.76 KB |

|    ORM |                        Method |  Return |     Mean |  StdDev |   Error |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
|------- |------------------------------ |-------- |---------:|--------:|--------:|-------:|-------:|-------:|----------:|
| Dapper |        QueryFirstOrDefault<T> |    Post | 114.1 us | 2.80 us | 4.23 us | 1.8750 | 0.8750 |      - |  11.35 KB |
| Dapper |         'Query<T> (buffered)' |    Post | 115.5 us | 1.30 us | 1.97 us | 2.6250 | 1.0000 | 0.3750 |  11.64 KB |
| Dapper |  QueryFirstOrDefault<dynamic> | dynamic | 120.8 us | 2.99 us | 4.53 us | 3.6250 |      - |      - |  11.39 KB |
| Dapper |   'Query<dynamic> (buffered)' | dynamic | 123.7 us | 3.61 us | 5.46 us | 2.0000 | 1.0000 |      - |  11.72 KB |
| Dapper |              'Contrib Get<T>' |    Post | 129.2 us | 2.79 us | 4.22 us | 2.0000 | 1.0000 |      - |  12.28 KB |
| Dapper |       'Query<T> (unbuffered)' |    Post | 163.0 us | 3.67 us | 6.17 us | 2.2500 | 1.0000 | 0.2500 |  11.76 KB |
| Dapper | 'Query<dynamic> (unbuffered)' | dynamic | 167.2 us | 0.73 us | 1.10 us | 2.2500 | 1.0000 |      - |   11.8 KB |

...in short: it's within the jitter on this laptop and no difference is discernable. It's worth looking at for performance because these are hot paths. I want to de-dupe the repeated code here, but given the hot path nature whether it inlines is important.
2020-05-07 07:21:39 -04:00
Nick Craver f486848e88 Update benchmarks (#1451)
This fixes things for `netcoreapp3.1` and fixes the outstanding #1205.
2020-05-02 11:12:58 -04:00
Nick Craver 601a5c28fb Fix for #1202
Behavior is expected, but doc isn't clear - clarifying!
2020-05-02 10:19:16 -04:00
Damir AinullinandNick Craver 9b010240c7 Set initial capacity for collections (#1449)
* Set initial capacity for collections
* Revert Massive changes

Co-authored-by: Nick Craver <nrcraver@gmail.com>
2020-05-02 08:15:46 -04:00
Nick Craver 663588f90b AppVeyor: Build tweaks & misc fixes (#1450)
Simplifying and improve build speed.

- Decreases builds from 8-13 minutes down to ~2 minutes (while running more tests)
- Moves to SQL Server 2019 on AppVeyor
- Moves the 2 longest running tests with params to `[FactLongRunning]`
- Bumps tests up to `netcoreapp3.1`
- Also fixes .Contrib tests
- Moves to `Build.csproj`
- Simplifies `build.ps1`
- Removed defunct `build.sh`
- Nukes `IsAppveyor` (moves to environmental variable overloads)
- Builds now work in Linux/macOS
2020-05-02 07:52:40 -04:00
5c87dc9738 SqlBuilder Support Update Set (#1404)
I add update `Set` method and unit test.

e.g: 
```C#
var sb = new SqlBuilder()
       .Set("vip = @vip", new { vip })
       .Set("updatetime = @updatetime", new { updatetime })
       .Where("id = @id", new { id })
;
var template = sb.AddTemplate("update #Users /**set**/ /**where**/");
connection.Execute(template.RawSql, template.Parameters);
```

RawSql will generate : 
```
update #Users Set vip = @vip , updatetime = @updatetime\n WHERE id = @id\n
```

using Dapper Execute in sqlserver it'll reqeust by below sql command
```
exec sp_executesql N'update #Users Set vip = @vip , updatetime = @updatetime
 WHERE id = @id
',N'@vip bit,@updatetime datetime,@id int',@vip=1,@updatetime='2020-01-01 00:00:00',@id=1
```

Co-authored-by: Nick Craver <nrcraver@gmail.com>
Co-authored-by: Nick Craver <craver@stackoverflow.com>
2020-05-01 19:25:12 -04:00
JulianRooze 2c81a4085a Fix handling of selecting nullable value tuples (#1400)
`SingleOrDefault<(int, int)?>(query)` always returned null because the IsValueTuple did not handle nullable types and thus the `GenerateValueTupleDeserializer` method was never called.

I've added test for the case when the query does not return something (the tuple should be null) and when it does return something. Additionally added tests for the edge-case where you select 8 or 15 element tuples to make sure nothing broke there.
2020-05-01 18:16:23 -04:00
0e04fe1daf Added EF6 performance tests back in netcoreapp3.0 (#1361)
* Added EF6 tests in netcoreapp3.0

* Fix up EF Core ref to always be 6.3.0

Co-authored-by: Alex Bagnolini <alex.bagnolini@ericsoft.com>
Co-authored-by: Nick Craver <craver@stackoverflow.com>
2020-05-01 18:03:52 -04:00
Nick CraverandYoussef Victor c6952825e8 Update Dapper.Rainbow/Snapshotter.cs
Co-authored-by: Youssef Victor <31348972+Youssef1313@users.noreply.github.com>
2020-05-01 17:36:34 -04:00
bryancrosby 9b6c8c7d7f Fix typo in Snapshotter
Fix small typo and grammar
2020-05-01 17:36:34 -04:00
Chris Donnelly 6aece653be MightyOrm needs a nonstandard connection string.
We are now providing it programmatically so we don't disrupt SQL Server.
2020-05-01 17:27:11 -04:00
Chris Donnelly 455b3f3b11 Adding MightyOrm benchmark. 2020-05-01 17:27:11 -04:00
BlackjacketMack 0b17133fd8 Updated InListStringSplitCount comment to GTE.
The comment suggested that more than the number specified in InListStringSplitCount and it would start to use string_split.  However, it is greater-than-or-equal-to (GTE) the number specified by InListStringSplitCount.
2020-05-01 17:24:39 -04:00
Damir Ainullin 899c9feb63 Replaced constant with index in loop (#1443) 2020-04-28 19:59:12 +01:00
mgravell 7088263aff update release notes 2020-04-06 10:11:05 +01:00
Marc GravellandNick Craver 765300a32b Enable deterministic build (#1433)
* - enable deterministic build
- lib updates for core packages

* set source root if needed

* Restore VS test runner

xUnit won't run in VS without it :)

Co-authored-by: Nick Craver <craver@stackoverflow.com>
2.0.35
2020-04-05 13:43:31 +01:00
mgravell 4ad80f880e allow SDK roll-forward 2020-03-26 09:53:21 +00:00
Wei 61fa083ca3 Add unit test for SqlBuilder with Dapper query (#1369) 2019-12-24 14:14:13 -05:00
Bernard Vander Beken 1922ef4a8d Use consistent punctuation in XML comment (#1357) 2019-11-03 10:34:00 -05:00
Sébastien Ros a18dc63c68 Use InvariantCulture in FlexibleConvert (#1363)
In Sqlite, DateTime is stored as String, and custom serializers ultimately use Convert.ChangeType to do the conversion. The generated code however doesn't set the Invariant culture, and the conversion can fail if the current culture doesn't match the standard DateTime serialization format from Sqlite.
2019-10-25 08:10:24 +01:00
mgravell 247e498f0e since we're targeting net461 again, ensure contrib tests have coverage 2.0.30 2019-09-27 10:47:36 +01:00
Bernard Vander Beken daf5bea70a Fix spelling (#1340) 2019-09-27 10:42:54 +01:00
Damir Ainullin 981cfe4ddf Replaced ContainsKey and [] with TryGetValue (#1339) 2019-09-27 10:42:46 +01:00
Damir Ainullin d12f1aa999 Use loop variable instead of 0 (#1334)
* Use loop variable instead of 0

* Changed unit test, added additional nesting level
2019-09-27 10:41:49 +01:00
mgravell 7769253d59 framework and tooling lib updates; does *NOT* include the full corpus of 3rd party ADO.NET providers 2019-09-27 10:39:40 +01:00
Nick Craver 1481c4d379 Tooling and project updates (#1333)
This is a branch cleaning up old `#if` clauses, `.csproj` bits, Linux build compatibility, and a few other tid-bits (broken out by commit).

In general: we're on 3.0 tooling and all previous cruft has been removed.
2019-09-26 19:47:55 -04:00
Damir Ainullin 7cac38246a Replaced Connection with GetClosedConnection in some unit tests… (#1337)
…cording to their names.
2019-09-22 09:33:59 -04:00
Jesper Meyer 3b0cd9a9a1 Updated Hand Coded benchmarks (#1206)
Hand coded version did not operate under the same circumstances as others.

- Add CommandBehavior.SingleResult and CommandBehavior.SingleRow. All other framworks does this under the hood.
- Run SqlCommand.Prepare() (perhaps it should be benchmarked as "Compiled"?)
- Use GetNullableValue because it's easier to read and slightly faster
- _table.Rows was incrementally added, which made the benchmark run slower the longer it executed. Added _table.Rows.Clear() to prevent the growth.
- Changed select to use * like other benchmarks
2019-09-22 08:40:07 -04:00
Andrés 77cd19d0e9 Fix performance tests (#1331)
Hi!
This PR tries to fix Dapper.Performance.Tests, actually you can't get [MemoryDiagnoser](https://benchmarkdotnet.org/api/BenchmarkDotNet.Diagnosers.MemoryDiagnoser.html)  stats because 
```IDiagnoser.GetColumnProvider()``` method was gone on BenchmarkDotnet 0.11.2. I choose ```DefaultColumnProviders.Metrics``` because of [this](https://github.com/dotnet/BenchmarkDotNet/issues/1184#issuecomment-507377695), i think it's the most simple way to add stats now.

**Before**
![image](https://user-images.githubusercontent.com/34173061/65264060-1a5f7780-db0e-11e9-9c8c-bb4c69a808df.png)

**After**
![image](https://user-images.githubusercontent.com/34173061/65264158-4f6bca00-db0e-11e9-9313-597b09070ae6.png)

On the other hand i choose removing ```[Ordered]``` as temporal solution of https://github.com/dotnet/BenchmarkDotNet/issues/1238, and yeah, the results are still ordered because of https://github.com/StackExchange/Dapper/blob/9282ef2872e1c82c68c86f31e93e8f1ceaacd409/Dapper.Tests.Performance/Config.cs#L42

**Before**
![image](https://user-images.githubusercontent.com/34173061/65264660-6232ce80-db0f-11e9-9046-9c2d8fc5e2d8.png)

**After**
 (No errors)

Thanks for all!!
2019-09-22 08:12:22 -04:00
Damir Ainullin 4dbf74f4d1 Replaced WriteLine with WriteLineColor 2019-09-22 07:55:04 -04:00
james-hester-ah 61707905f6 Fix issue #418 for DeleteAsync (#1309)
Fix issue #418 for DeleteAsync (with tests)
2019-09-21 09:16:34 -04:00