New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support a "category" attribute for selecting benchmarks #248

Closed
jskeet opened this Issue Aug 19, 2016 · 11 comments

Comments

Projects
None yet
5 participants
@jskeet

jskeet commented Aug 19, 2016

In Noda Time, I've found it useful to be able to categorize benchmarks. For example, I have a "BCL" category, and a "Text" category. Categories can be applied to classes or methods. From the command line, you can include or exclude specific categories.

Would love to see this in BenchmarkDotNet.

@AndreyAkinshin

This comment has been minimized.

Show comment
Hide comment
@AndreyAkinshin

AndreyAkinshin Sep 23, 2016

Member

I like this feature, but I'm not sure how to implement it. I have two questions:

  1. How we should name the attribute? I like Category, but it could conflict with other Category attributes (it's a common name, a lot of libraries use it for own purposes). Maybe BenchmarkCategory?
  2. Should we use categories only in the command line or it should also affect exporers/summary? If we want to have it in the summary, how it should be displayed? Especially, I'm worried about methods which belong to multiple categories.
Member

AndreyAkinshin commented Sep 23, 2016

I like this feature, but I'm not sure how to implement it. I have two questions:

  1. How we should name the attribute? I like Category, but it could conflict with other Category attributes (it's a common name, a lot of libraries use it for own purposes). Maybe BenchmarkCategory?
  2. Should we use categories only in the command line or it should also affect exporers/summary? If we want to have it in the summary, how it should be displayed? Especially, I'm worried about methods which belong to multiple categories.
@jskeet

This comment has been minimized.

Show comment
Hide comment
@jskeet

jskeet Sep 23, 2016

I'm fine with BenchmarkCategory. I don't have enough understanding of the details of BenchmarkDotNet to comment, but I know I'd personally be interested in using it for filtering, primarily... but it would be nice to know which category any benchmark is in for filtering post-run as well. ("Show me how all the text handling benchmarks have gone over time.")

jskeet commented Sep 23, 2016

I'm fine with BenchmarkCategory. I don't have enough understanding of the details of BenchmarkDotNet to comment, but I know I'd personally be interested in using it for filtering, primarily... but it would be nice to know which category any benchmark is in for filtering post-run as well. ("Show me how all the text handling benchmarks have gone over time.")

@AndreyAkinshin

This comment has been minimized.

Show comment
Hide comment
@AndreyAkinshin

AndreyAkinshin Sep 23, 2016

Member

Ok, we could use it in Csv and Json exporters and ignore in the summary.

Member

AndreyAkinshin commented Sep 23, 2016

Ok, we could use it in Csv and Json exporters and ignore in the summary.

@roji

This comment has been minimized.

Show comment
Hide comment
@roji

roji Sep 24, 2016

Contributor

+1 for this. One additional idea would be to have the BenchmarkSwitcher support categories as well. Once you start having lots of benchmarks the switcher quickly becomes very hard to work with, the switcher could first present the user with the list of categories, and after category selection, the benchmarks in that category.

Contributor

roji commented Sep 24, 2016

+1 for this. One additional idea would be to have the BenchmarkSwitcher support categories as well. Once you start having lots of benchmarks the switcher quickly becomes very hard to work with, the switcher could first present the user with the list of categories, and after category selection, the benchmarks in that category.

@NickCraver

This comment has been minimized.

Show comment
Hide comment
@NickCraver

NickCraver May 11, 2017

Member

I have a related use case here that could be satisfied by the same feature, I'd like to run all benchmarks in an assembly and see the results in a single output.

Concrete case: in Dapper I have a class w/ benchmarks for each ORM, this is because their setup is different and one monolithic class with tons of setup for no good reason is very inefficient, slow, and possibly full of side-effects. A small class is easy to add, maintain, etc. and keeps [Setup] simple/efficient as well.

If we could run all of them (or a * category, or give them all the same category, w.r.t. this issue), life would be much easier. For example we could compare all of the "select many", "select single", "select dynamic", etc. methods across benchmarks very cleanly while also having easy-to-maintain code.

Like @roji mentions above, BenchmarkSwitcher support would be huge, even if it were .RunCategories() or some such to not break existing behavior.

Member

NickCraver commented May 11, 2017

I have a related use case here that could be satisfied by the same feature, I'd like to run all benchmarks in an assembly and see the results in a single output.

Concrete case: in Dapper I have a class w/ benchmarks for each ORM, this is because their setup is different and one monolithic class with tons of setup for no good reason is very inefficient, slow, and possibly full of side-effects. A small class is easy to add, maintain, etc. and keeps [Setup] simple/efficient as well.

If we could run all of them (or a * category, or give them all the same category, w.r.t. this issue), life would be much easier. For example we could compare all of the "select many", "select single", "select dynamic", etc. methods across benchmarks very cleanly while also having easy-to-maintain code.

Like @roji mentions above, BenchmarkSwitcher support would be huge, even if it were .RunCategories() or some such to not break existing behavior.

@AndreyAkinshin

This comment has been minimized.

Show comment
Hide comment
@AndreyAkinshin

AndreyAkinshin May 11, 2017

Member

Hey @NickCraver. First of all, there is a workaround that you can use right now, here is an example:

[DryJob]
public class A
{
    [Benchmark]
    public void A1() => Thread.Sleep(10);
    
    [Benchmark]
    public void A2() => Thread.Sleep(10);
}

[DryJob]
public class B
{
    [Benchmark]
    public void B1() => Thread.Sleep(10);
    
    [Benchmark]
    public void B2() => Thread.Sleep(10);
}

internal class Program
{
    public static void Main(string[] args)
    {
        var benchmarks = new List<Benchmark>();
        benchmarks.AddRange(BenchmarkConverter.TypeToBenchmarks(typeof(A)));
        benchmarks.AddRange(BenchmarkConverter.TypeToBenchmarks(typeof(B)));
        BenchmarkRunner.Run(benchmarks.Where(b => b.Target.Method.Name.Contains("1")).ToArray(), null);
    }
}

Such approach allows combining specific set of benchmark methods from different types in one summary table.
However, we need an API which provides a nice way to do it. There is no problem to add the BenchmarkCategory attribute. Last time I was stuck with the API design.

My current suggestions:

  • We can add a boolean flag to all BenchmarkSwitcher methods which allow combining all the benchmarks in a single summary table
  • We can add the following property to IConfig:
IEnumerable<IFilter> GetFilters();

By default, it will return an empty enumerable which will mean that we want to run all the benchmarks. The interface will contain single method:

public interface IFilter
{
    bool Predicate(Benchmark benchmark);
}

And it would be easy to implement CategoryFilter:

public class CategoryFilter: IFilter
{
    public CategoryFilter(params string[] categories)
}

Since it's a part of IConfig, such filter can be added manually or via command line.
Open question:

  • Should we run benchmarks which have all the target categories or at least one? Maybe it makes sense to introduce something like enum UnionPolicy { Any, All }.
  • Should we run benchmarks which match all the target filters or at least one? Or maybe we should use the same enum here?

@NickCraver, will this be enough? Do you need any additional features here?

@adamsitnik, @mattwarren, @jskeet, what do you think about the suggested API?

Member

AndreyAkinshin commented May 11, 2017

Hey @NickCraver. First of all, there is a workaround that you can use right now, here is an example:

[DryJob]
public class A
{
    [Benchmark]
    public void A1() => Thread.Sleep(10);
    
    [Benchmark]
    public void A2() => Thread.Sleep(10);
}

[DryJob]
public class B
{
    [Benchmark]
    public void B1() => Thread.Sleep(10);
    
    [Benchmark]
    public void B2() => Thread.Sleep(10);
}

internal class Program
{
    public static void Main(string[] args)
    {
        var benchmarks = new List<Benchmark>();
        benchmarks.AddRange(BenchmarkConverter.TypeToBenchmarks(typeof(A)));
        benchmarks.AddRange(BenchmarkConverter.TypeToBenchmarks(typeof(B)));
        BenchmarkRunner.Run(benchmarks.Where(b => b.Target.Method.Name.Contains("1")).ToArray(), null);
    }
}

Such approach allows combining specific set of benchmark methods from different types in one summary table.
However, we need an API which provides a nice way to do it. There is no problem to add the BenchmarkCategory attribute. Last time I was stuck with the API design.

My current suggestions:

  • We can add a boolean flag to all BenchmarkSwitcher methods which allow combining all the benchmarks in a single summary table
  • We can add the following property to IConfig:
IEnumerable<IFilter> GetFilters();

By default, it will return an empty enumerable which will mean that we want to run all the benchmarks. The interface will contain single method:

public interface IFilter
{
    bool Predicate(Benchmark benchmark);
}

And it would be easy to implement CategoryFilter:

public class CategoryFilter: IFilter
{
    public CategoryFilter(params string[] categories)
}

Since it's a part of IConfig, such filter can be added manually or via command line.
Open question:

  • Should we run benchmarks which have all the target categories or at least one? Maybe it makes sense to introduce something like enum UnionPolicy { Any, All }.
  • Should we run benchmarks which match all the target filters or at least one? Or maybe we should use the same enum here?

@NickCraver, will this be enough? Do you need any additional features here?

@adamsitnik, @mattwarren, @jskeet, what do you think about the suggested API?

@AndreyAkinshin AndreyAkinshin self-assigned this May 11, 2017

NickCraver added a commit to StackExchange/Dapper that referenced this issue May 11, 2017

Benchmarks v2: BenchmarkDotNet and friends
This is based on BenchmarkDotNet (while preserving the legacy format
with minor improvements as well - legacy runs much faster). See #666 for
details. Not an ominus number at all.

Note: this code will get a bit simpler with BenchmarkDotNet categories,
see dotnet/BenchmarkDotNet#248 for details.
@adamsitnik

This comment has been minimized.

Show comment
Hide comment
@adamsitnik

adamsitnik May 11, 2017

Member

I had similar issues when I wanted to benchmark Array vs Span vs List.

I think that if we add [Category] attribute or property to the [Benchmark] attribute we should get what we all want. Benchmark switcher could then offer to choose whole category or given type. Sample:

class ArrayBenchmarks
{
    [Benchmark(Baseline = true, Category = "Indexers"]
    public int IndexerArray() => array[0];
}

class SpanBenchmarks
{
    [Benchmark(Category = "Indexers"]
    public int IndexerSpan() => span[0];
}

And then sample Benchmark Switcher output could be:

Available Benchmarks:
  #0  Category: Indexers
  #1  ArrayBenchmarks
  #2  SpanBenchmarks

Another thing would be new overload BenchmarkRunner.Run(string categoryName) plus support of the --category parameter in console parser.

But I am not sure how to differentiate whole group of benchmarks (for example CollectionsBenchmark category) vs specialized category (for example "IndexerBenchmarks")

Member

adamsitnik commented May 11, 2017

I had similar issues when I wanted to benchmark Array vs Span vs List.

I think that if we add [Category] attribute or property to the [Benchmark] attribute we should get what we all want. Benchmark switcher could then offer to choose whole category or given type. Sample:

class ArrayBenchmarks
{
    [Benchmark(Baseline = true, Category = "Indexers"]
    public int IndexerArray() => array[0];
}

class SpanBenchmarks
{
    [Benchmark(Category = "Indexers"]
    public int IndexerSpan() => span[0];
}

And then sample Benchmark Switcher output could be:

Available Benchmarks:
  #0  Category: Indexers
  #1  ArrayBenchmarks
  #2  SpanBenchmarks

Another thing would be new overload BenchmarkRunner.Run(string categoryName) plus support of the --category parameter in console parser.

But I am not sure how to differentiate whole group of benchmarks (for example CollectionsBenchmark category) vs specialized category (for example "IndexerBenchmarks")

@AndreyAkinshin

This comment has been minimized.

Show comment
Hide comment
@AndreyAkinshin

AndreyAkinshin May 11, 2017

Member

@adamsitnik, see original request by Jon Skeet:

Categories can be applied to classes or methods.

The [Benchmark(Category = "Indexers"] approach looks nice, but it can't be applied to classes.

Member

AndreyAkinshin commented May 11, 2017

@adamsitnik, see original request by Jon Skeet:

Categories can be applied to classes or methods.

The [Benchmark(Category = "Indexers"] approach looks nice, but it can't be applied to classes.

@NickCraver

This comment has been minimized.

Show comment
Hide comment
@NickCraver

NickCraver May 11, 2017

Member

@AndreyAkinshin First, thanks for the workaround - that unblocked me in Dapper and it's much appreciated! I like the API ideas, I guess the big question is whether a benchmark is in 1 or many categories. I'd certainly say it's the latter, which would affect attribute names...or maybe not.

What if it was:

[BenchmarkCategory("dynamic","list")]

via a params on the attribute? It wouldn't preclude a property on [Benchmark], but since that both can't be applied to classes and would imply only a single category is available it's confusing in several ways. I'd agree with only having it as a separate attribute.

I also have use cases for the union descriptor in Dapper as well (e.g. run all dynamic classes, or list classes, or the combination, etc.) so +1 to that.

Related: possibly built-in CategoryColumn to go along with this for easy usage?

Member

NickCraver commented May 11, 2017

@AndreyAkinshin First, thanks for the workaround - that unblocked me in Dapper and it's much appreciated! I like the API ideas, I guess the big question is whether a benchmark is in 1 or many categories. I'd certainly say it's the latter, which would affect attribute names...or maybe not.

What if it was:

[BenchmarkCategory("dynamic","list")]

via a params on the attribute? It wouldn't preclude a property on [Benchmark], but since that both can't be applied to classes and would imply only a single category is available it's confusing in several ways. I'd agree with only having it as a separate attribute.

I also have use cases for the union descriptor in Dapper as well (e.g. run all dynamic classes, or list classes, or the combination, etc.) so +1 to that.

Related: possibly built-in CategoryColumn to go along with this for easy usage?

@AndreyAkinshin

This comment has been minimized.

Show comment
Hide comment
@AndreyAkinshin

AndreyAkinshin May 13, 2017

Member

@NickCraver, I implemented all the features (you can try 0.10.6.186 from our nigtly feed https://ci.appveyor.com/nuget/benchmarkdotnet). Let me know if you need something else. If everything is fine, I will release new version soon. You can find some docs below:

Filters

Sometimes you don't want to run all of your benchmarks.
In this case, you can filter some of them with the help of filters.

Predefined filters:

  • SimpleFilter
  • NameFilter
  • DisjunctionFilter
  • CategoryFilter
  • AnyCategoriesFilter
  • AllCategoriesFilter

Usage examples:

[Config(typeof(Config))]
public class IntroFilters
{
    private class Config : ManualConfig
    {
        // We will benchmark ONLY method with names with names
        // (which contains "A" OR "1") AND (have length < 3)
        public Config()
        {
            // benchmark with names which contains "A" OR "1"
            Add(new DisjunctionFilter(
                new NameFilter(name => name.Contains("A")),
                new NameFilter(name => name.Contains("1"))
            ));

            // benchmark with names with length < 3
            Add(new NameFilter(name => name.Length < 3));
        }
    }

    [Benchmark] public void A1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void A2() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void A3() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void B1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void B2() => Thread.Sleep(10);
    [Benchmark] public void B3() => Thread.Sleep(10);
    [Benchmark] public void C1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void C2() => Thread.Sleep(10);
    [Benchmark] public void C3() => Thread.Sleep(10);
    [Benchmark] public void Aaa() => Thread.Sleep(10);
}
[DryJob]
[CategoriesColumn]
[BenchmarkCategory("Aswesome")]
[AnyCategoriesFilter("A", "1")]
public class IntroCategories
{
    [Benchmark]
    [BenchmarkCategory("A", "1")]
    public void A1() => Thread.Sleep(10); // Will be benchmarked
    
    [Benchmark]
    [BenchmarkCategory("A", "2")]
    public void A2() => Thread.Sleep(10); // Will be benchmarked

    [Benchmark]
    [BenchmarkCategory("B", "1")]
    public void B1() => Thread.Sleep(10); // Will be benchmarked
    
    [Benchmark]
    [BenchmarkCategory("B", "2")]
    public void B2() => Thread.Sleep(10);
}

Command line examples:

--category=A
--allCategories=A,B
--anyCategories=A,B

If you are using BenchmarkSwitcher and want to run all the benchmarks with a category from all types and join them into one summary table, use the --join option (or BenchmarkSwitcher.RunAllJoined):

* --join --category=MyAwesomeCategory
Member

AndreyAkinshin commented May 13, 2017

@NickCraver, I implemented all the features (you can try 0.10.6.186 from our nigtly feed https://ci.appveyor.com/nuget/benchmarkdotnet). Let me know if you need something else. If everything is fine, I will release new version soon. You can find some docs below:

Filters

Sometimes you don't want to run all of your benchmarks.
In this case, you can filter some of them with the help of filters.

Predefined filters:

  • SimpleFilter
  • NameFilter
  • DisjunctionFilter
  • CategoryFilter
  • AnyCategoriesFilter
  • AllCategoriesFilter

Usage examples:

[Config(typeof(Config))]
public class IntroFilters
{
    private class Config : ManualConfig
    {
        // We will benchmark ONLY method with names with names
        // (which contains "A" OR "1") AND (have length < 3)
        public Config()
        {
            // benchmark with names which contains "A" OR "1"
            Add(new DisjunctionFilter(
                new NameFilter(name => name.Contains("A")),
                new NameFilter(name => name.Contains("1"))
            ));

            // benchmark with names with length < 3
            Add(new NameFilter(name => name.Length < 3));
        }
    }

    [Benchmark] public void A1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void A2() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void A3() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void B1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void B2() => Thread.Sleep(10);
    [Benchmark] public void B3() => Thread.Sleep(10);
    [Benchmark] public void C1() => Thread.Sleep(10); // Will be benchmarked
    [Benchmark] public void C2() => Thread.Sleep(10);
    [Benchmark] public void C3() => Thread.Sleep(10);
    [Benchmark] public void Aaa() => Thread.Sleep(10);
}
[DryJob]
[CategoriesColumn]
[BenchmarkCategory("Aswesome")]
[AnyCategoriesFilter("A", "1")]
public class IntroCategories
{
    [Benchmark]
    [BenchmarkCategory("A", "1")]
    public void A1() => Thread.Sleep(10); // Will be benchmarked
    
    [Benchmark]
    [BenchmarkCategory("A", "2")]
    public void A2() => Thread.Sleep(10); // Will be benchmarked

    [Benchmark]
    [BenchmarkCategory("B", "1")]
    public void B1() => Thread.Sleep(10); // Will be benchmarked
    
    [Benchmark]
    [BenchmarkCategory("B", "2")]
    public void B2() => Thread.Sleep(10);
}

Command line examples:

--category=A
--allCategories=A,B
--anyCategories=A,B

If you are using BenchmarkSwitcher and want to run all the benchmarks with a category from all types and join them into one summary table, use the --join option (or BenchmarkSwitcher.RunAllJoined):

* --join --category=MyAwesomeCategory

@adamsitnik adamsitnik added this to the v0.10.7 milestone Sep 2, 2017

@adamsitnik

This comment has been minimized.

Show comment
Hide comment
@adamsitnik

adamsitnik Sep 2, 2017

Member

It was release as part of 0.10.7, I am closing this one

Member

adamsitnik commented Sep 2, 2017

It was release as part of 0.10.7, I am closing this one

@adamsitnik adamsitnik closed this Sep 2, 2017

joangilabert added a commit to joangilabert/dapper-dot-net that referenced this issue Apr 16, 2018

actualizacion desde el original (#1)
* Tests: add 4 attempts to repro #457

* Change CE package to one that might work

* Fix *all* the CE references

* Don't attempt to load native assemblies on DNX

* Detect app-veyor for MySql/Postgresql

* Standardize on test db for appveyor

* actual/expected in asserts are the wrong way round

All the tests are wrote in the form actual.IsEqualTo(expected). This
made for some odd error messages when a test failed.

* Initial test setup for #461; note that this does not repro, due to running on SQL-Server - needs to be changed to SQLite to repro

* Fix #461 - change FindConstructor to allow parameters that have a type-handler defined

* New feature: PadListExpansions - reduces query plan saturation by padding "in" lists and populating with nulls; opt-in (see remarks on setting)

* 1.50-beta8 deploy

* Fix typos in the comments for PadListExpansions

* Test for SO35470588

* Readme.md: update performance tests link

* Example for SO35554284

* Add SQLITE to test builds; add tests for issues #466 and #467; fix #466 by adding retry-with-fallback flags strategy

* Update to sqlite rc2, because without that nothing works; add extra tests around sqlite oddities; update tests to reflect sqlite rc2 fixes

* Fix #468 - CreateParamInfoGenerator should treat enums as primitives, not box them as enums

* Don't check for null in the basic enum case

* Support get-only C# 6 properties, i.e. `public int Id {get;}`

* prefer an exact-case backing-field match over a wrong-case regular field (essentially: this promotes get-only properties over regular fields)

* Support xml types by default (XmlDocument, XDocument, XElement) - fix #427

* Set the DbType for XmlDocument / XDocument / XElement

* When doing list expansions (6=>10 etc), use the last non-trivial value - do *NOT* use null, as it causes problems with "not in" clauses; add test for the same

* Recreate all the xproj to reflect the current tooling - old versions break VS15; enable XDocument etc in corefx (#if block was too large)

* Heh, AspNet and DNX (only) work in VS2015; DNX and DotNet (only) work in VS15; I guess we need to use DNX for now, then, as the only one that works in both.

* 1.50-beta9

* Unify test credentials for MySQL; add passing test for SO36303462

* Bumping dependencies version numbers

* Revert "Bumping dependencies version numbers"

This reverts commit 70ee9a7.

* Readme: Better explanation for multi mapping

* fix outpt paths

* Get building

* PowerShell build scripts

* PowerShell build updates: include .Contrib

* PowerShell build script love

* Add bash build scripts

Note: these are hosed on OS X due to file handle limits, see
dotnet/cli#809 for details.

* Bash build: fix test runner on OS X

Note: no tests pass because there’s no integrated security option (or
widely available SQL server) on OS X at the moment. But the build and
test runners are up and going.

* Update .gitgnore for build pathing

* .Net Core: remove floating versions (use stable ones on Nuget.org) and get this puppy back in action.

Also: it's 2016.

* Add newer feed back **only for the tests projects**, Sqlite for example has bugs in rc1-final fixed in rc2-15948

* Nuget.org feed only, skip the 2 Sqlite tests until RC2+ packages with the fix are out of pre-release.

* Fix assembly name for Contrib tests

* Runtimes fix, per dotnet/cli#2578

* Fix EntityFramework.StrongName build for RC2

* Update to RC2 final build (24027) libraries. Also bump to beta10

* RC2: Remove CoreFX #1612 blocker - fix is released, yay!

dotnet/corefx#1612 is now closed, tests
working.

* Upgrade project.json files to RC2 format.

Note: on a nuspec comparison, the following dependencies aren't there
anymore: Microsoft.CSharp, mscorlib, System, and System.Core aren't
explicitly specified in frameworkAssemblies anymore. The only one of
these I can imagine mattering is Microsoft.CSharp.

* It's time for appveyor.yml

Tooling changes need to live in the repo now so the build doesn't FUBAR
every time we change the script.

* It took several people a while to find this one.

* RC2 Version bump, since we locked ourselves in with semver on beta9

* Update build scripts to pack for us

* JSON RC2 fixes

* Interfaces are back, simplifying code.

Related issue: #520

* net451 test prep (not quite ready - SQL Geo and interop failing)

* XMLDoc fixes for latest methods and missing DataSet in .NET Core

* .xproj: RC2 upgrade

This fixes null refs with the DNX MSBuild targets when building from
Visual Studio.

* Switch version suffix to be a build parameter

Note: build.sh needs love from OS X/*nix later to match

* This .0 addition happens automatically...make it explicit instead.

* git blame game

* Test for #524 (believed to be a failing test; cannot validate or Fix until I get the latest tooling installed)

* Fix #524 - `GridReader` should use the same conversion code as the regular reader

* Add InListStringSplitCount; when set, causes `in @foo` parameters to be implemented using string_split

* fix case of generated SQL in string-split

* Dapper.EF.StrongName: should snk for *all* builds!

* Fixed some syntax errors in project.json files.

* .Net Core 1.0 RTM update

* Remove a bunch of unnecessary (and *theoretically* dangerous, in a very unlikely scenario involving custom cultures installed on a box) C# 7 string $"...{...}..." usages

* Simplify the string_split implementation

* 1.50.1 deploy

* Rename DataTable=>DapperTable; fix #549

* Failing test for #552

* (just to prove that #552 still happens even if the only values seen are 0 and 1)

* Fix for #569

* 1.50.2

* Repackage Dapper.EF to fix System.Runtime; deploy as .52; fix xunit refs; add test for #570

* Added tests to complement documentation of pseudo-positional parameters

* Fix SqlBuilder.OrWhere method which was actually yielding an 'AND WHERE' statement.

* Operate on db records instead of files.

* Add CommannDefinition versions of Query(First,FirstOrDefault,Single,SingleOrDefault)Async and a few unit tests for them

* Improve tests

* failing test for #563

* fix broken test to actually include the error!

* Make CommandBehavior more configurable; default to SingleRow=allowed,SingleResult=disallowed - but expose options; this fixes issues like #563 automatically, and allows the performance aspect  of #554 to be fixed via a global setting

* support for international parameter names (regex categories); fix #601

* Add some <remarks> to the new options

* Capitalization

* Update readme.md

Missed second bracket in ID example

* Set true to GridReader.IsConsumed when MultiReadInternal is called

* Non-greedy match for comments regex

Fixes #436, #280
My editor has also normalized a few line endings to LF like 99% of the
file was.

* Fix #634 - dapper now handles connection lifetime and has for ages

* 1.50.3-beta1: looks at #637  re `Guid`

* Toolng cheese move - lock in preview2 for now.

* Fix Contrib test resolution

Note: there's still a 1.0.0 vs 1.1.0 quirk here - digging.

* Add SqlMapper.RemoveTypeMap() method

* Update Readme.md

* Add test DiscriminatedUnionWithMultiMapping

DiscriminatedUnionWithMultiMapping - test for check correct MultiMapping (splitOn) functionality with discriminated row parser.

* added firebird support

added firebird sql adapter to allow record insert and key retrieving

* Revert "1.50.3-beta1: looks at #637  re `Guid`"

This reverts commit 91725fb.

* Update README with documentation for [ExplicitKey] attribute

* Add GetRowParser documentation/example

* Fix missing Firebase Async, issue #695

TODO: All of these need race love in V2, complete re-vamp.

* Rename package to "Dapper"

Related: #683

* Remove note about requiring open connections

* Added Belgrade Sql Client

In the performance benchmark is added Belgrade Sql client data access
library (https://github.com/JocaPC/CLR-Belgrade-SqlClient). This is a
wrapper around ADO.NET classes that executes queries in async manner
using callbacks. "Belgrade.Sql.Client": "0.6.2" is aded in project.json
file, and new flag "BELGRADE" controls should the test be executed.

* migrate release notes to [master]/docs

* Set theme jekyll-theme-cayman

* Add a full stop just so I can tell if the docs migration is working

* Fix Dapper release notes link

* Security!

* Fixed test issue in Simple.Data performance test (#723)

* Added fix for Simple.Data tast

Due to the missing .FirstOrDefault() in Simple.Data test, performance
numbers for Simple.Data were too high (better than hand coded data
reader). Added FirstOrDefault() to actually fetch the data.

* VS 2017 .csproj Migration
Due to the way VS test works (by injecting an executable entry point), the performance tests needed to be factored out. I also organized all of our existing tests better along the way.
Actual code changes to Dapper itself are very minor, only formatting and documentation fixes (which we need many more of).

The build.ps1 script is upated to work, but note that <frameworkAssemblies> is not working in .nuspec inside the packages in the new .csproj system. I consider this to be a blocker. Issue is here: NuGet/Home#4853

* Correct minor typographical error in Readme.md (#732)

Under the `List Support` section, the sentence opens with `Dapper allow you`, which should instead be `Dapper allows you`. This PR will correct this mistake, restoring balance to the universe.

After originally spotting this, the most minor of mistakes, I decided to leave it and move on with my life, since it likely effected nobody. Four hours passed and the thought that it existed unchecked had fully manifested itself within my subconscious and I was no longer able to continue with my existence knowing that I had seen this mistake and not exercised my power to correct it.

Thank you, and sorry.

* Define expected behaviour for value-tuple parameters and returns, and implement

* remove redundant test code (oops)

* Better matching of value-tuple names when wrong number of columns - should return nulls for unmapped

* Add tests for the too few/too many columns scenarios for value-tuples; happy to discuss alternative expectations

* Fix Readme typos (#739)

* Readme.md: Fixed link to test suite (#764)

* VS 2017 Build - Making things work (#766)

* Progress on VS 2017 build tooling
* Finally, a working VS 2017 tooling build

* Update appveyor.yml for 2017 build

* Appveyor: update services

* Let's try this again

* Again!

* More path changes

* Appveyor: SQL 2016

* Appveyor: create databases

* Let's just keep adding YAML until this works.

* Appveyor: Formatting & combine init

* Appveyor: Update Postgres path

* Lots of documentation fixes/additions.

* Fix Microsoft.SqlServer.Types for new .csproj

* Fix type loads for the builds without SQL in the GAC

* Fix SQL spatial type loading

* Skip the MySQL FUBAR test

It's indeed broken on their end. We should consider switching providers,
e.g. https://github.com/mysql-net/MySqlConnector/

* Add build badge to README

* Appveyor: enable MyGet publishing

* Lots of code cleanup, no functional changes

* C# 7 cleanup: pattern matching for TryStringSplit

* Documentation: GridReader

* Documentation: contrib

* Documentation: EntityFramework

* Documentation: Rainbow

* Tests: make analyzers happy because why not

* Documentation and formatting: secondary types

* Documentation and formatting: SqlMapper

* Benchmarks v2: BenchmarkDotNet and friends

This is based on BenchmarkDotNet (while preserving the legacy format
with minor improvements as well - legacy runs much faster). See #666 for
details. Not an ominus number at all.

Note: this code will get a bit simpler with BenchmarkDotNet categories,
see dotnet/BenchmarkDotNet#248 for details.

* Dependency: Dapper doesn't need SqlClient, only Data.Common

* Benchmarks: customization and formatting

More cleanup to do (removing Type column next), but getting to some very
usable output now.

* netstandard2.0 functionality (w/ runtime breaks)

This adds a netstandard2.0 build to Dapper (and StrongName until v2),
adds a netstandard2.0 test lineup, restores most functionality (except
UDTs for SQL, e.g. .UdtTypeName isn't in netstandard2), and also breaks
things not actually implemented or implemented correctly in
netstandard2.0. Pushing this up so we can work through these with the
.NET teams.

Several things are still broken here (and fail tests):
- Parameter decimal values (not filed yet)
- DataTables as parameters
(dotnet/corefx#19708)
- .GetSchemaTable() (not yet filed, implementation is completely missing
from SqlDataReader in CoreFX)

While the compile is clean, the above are runtime issues.
`SqlParameter.UdtTypeName` is a separate issue, that one just wasn't in
`netstandard2.0` at all...so we can't support UDTs there until it is.
See dotnet/corefx#17126 for details.

* Fix MySQL tests and disposal (#774)

* Don't create the connection in Dispose: this avoids creating a SQLConnection simply to Dispose it.
* Run MySQL tests against the open MySqlConnection: 'connection' is a protected variable in the TestBase class that is a SQL Server connection, not a MySQL connection.
* Skip broken MySQL tests: as per issue #295, setting "AllowZeroDateTime=True" in the connection string causes an InvalidCastException in SqlMapper.

* Benchmarks: performance and formatting

* Minor README tweaks. (#776)

Use an HTTPS link where possible.
Fix 404 for performance tests.

* Fix for InsertAsync in PostgresAdapter (#689)

* Fix for PostgresAdapter in SqlMapperExtensions.Async. Copied same line of code from SqlMapperExtensions to fix RuntimeBinderException on InsertAsync
* Cleanup

* Try and use BenchmarkDotNet correctly

OperationsPerInvoke is an informational, not instructional property.
What we actually want is the UnrollFactor. Moved into the job definition
to simplify things.

* fix issue #731: AddDynamicParameters repeated if paramtype is DbStiring should work.

* Added EntityFrameworkCore performance tests (#778)

* Perf: add EntityFramework Core to legacy tests

* Markdown tables (#800)

Markdown tables instead of html
“Can be faster” in correct row

* Enable SqlDataRecord TVPs on corefx. (#801)

* Revert "Enable SqlDataRecord TVPs on corefx. (#801)" (#803)

This reverts commit e7ad087.

* Appveyor: use the VS 2017 preview image

* Avoid allocation for linq in CreateParamInfoGenerator and added some other micro optimizations

* Enable SqlDataRecord TVPs on netstandard1.3. (#802)

* Enable SqlDataRecord TVPs on netstandard1.3.
* Update netstandard2.0 SqlClient references to Preview 2.
* Skip TransactionScope tests for netcoreapp2.0.
- According to dotnet/corefx#12534, ambient transaction enlistment is not included with .net core 2.0.
* Update references in Dapper.StrongName.
* Disable parallel test run to stabilize flaky type handler tests.
* Disable parallel test run by assembly attribute.
* Move Issue461 tests to TypeHandlerTests.
* Group type handler tests in a collection, re-enable parallelization.
- Being part of the same collection, type handler tests will run sequentially. All other tests can run in parallel.
* Move tests relying on query cache & type maps to a separate collection.

* Upgade libs, fix tests

This uses the new non-parallel-at-the-end I added to xUnit in xunit/xunit#1411 This way we can run any global test that are other-test-unfriendly much more easily.

* More test fixes

* Appveypr: update to base 2017 image again

.NET Core 2 SDK is on the base Appveyor image now

* Update semver, add to solution

* Fix for #808

Add dynamic overloads for:
- QueryFirstAsync
- QueryFirstOrDefaultAsync
- QuerySingleAsync
- QuerySingleOrDefaultAsync

This may change a lot in 2.x, but many people asking for them now so here they are. Unit tests also fixed for QuerySingleOrDefaultAsync.

Note: this builds on the netstandard2 branch because of the xUnit changes to go with VS 2017 15.3.

* Fix for #815

New overload so this isn't a breaking change. We can collapse down in v2.0 (including the Impl method).

* Update README to remove advetisements

* Tests: xUnit cleanup

This change:
- Removes the Assert shim
- Uses recommended xUnit methods (improving fail errors)
- Cleans up exception tests
- General test formatting fixes
- Removes the netcoerapp1.0 only testing (oops commit)

* Cleanup

* Fix unit tests

* Update README for new assertions

* net40 is dead - remove #if ASYNC bits

* .editorconfig and formatting

* Misc build analyzer fixups

* Lib updates and prep for netstandard2.0 alpha

* Dapper.Contrib: netstandard2.0

* Fix build script

Removes NuGet workaround for pre-2.0 and lines up with other script
enhancements since.

* MyGet feed!

Adding a dapper specific feed, for much easier pushing to NuGet. When
they implement Ctrl+Click in the UI this won't be necessary...or we
break down and automate it finally. Depends on signing plans later.

* Add literal replacement example to readme

* Additional notes on literal replacements

* words are hard

* Tests for DateTime2 compatibility

This shows the importance of using DbType.DateTime2 in Dynamic Parameters to avoid precision truncation

* Shortened the changes

Combined 2 tests into one

* when inserting, check if type implements IEnumerable<T> to determine if it's a collection (#880)

* when inserting check if type implements IEnumerable<T> to determine if it's a collection
* when inserting, check if type is a collection by comparing its implemented interfaces to unbound generic type IEnumerable<> instead of the name "IEnumerable`1"

* bump semver for next release

* Ignore .vscode/

* 1.50.4 release

* Bump semver for next release to 1.50.5-alpha*

* Fix benchmark description typos (#932)

* fix equal tests (#944)

* fix equal tests

* fix test

* Test and fix for #591

This brings behavior QueryAsync behavior on par with Query (sync) and properly returns nothing when an empty result set is encountered.

* Code formatting fix (tabs to spaces) (#896)

* Make DapperRow implement IReadOnlyDictionary<string, object> (#913)

* Change to GetAll to allow the usage of a nullable type in T when T is an interface… #933 (#936)

* Change to GetAll to allow the usage of a nullable type in T when T is an interface.

* Change to GetAll to allow the usage of a nullable type in T when T is an interface: further change to check if val == null and if so then don't try to assign it as a property value.

* Change to Get to allow the usage of a nullable type in T when T is an interface. (effectively the same change as the previous change to GetAll.)

* Change to GetAsync and GetAllAsync to allow the usage of a nullable type in T when T is  an interface.

* Added in UserWithNullableDob and IUserWithNullableDob.

Added in tests for GetAndGetAllWithNullableValues and  GetAsyncAndGetAllAsyncWithNullableValues.

* Added in .ConfigureAwait(false) in the GetAsync Test.
Added comment to identify which issue the test relates to.

* Added NullableDates tables to the test databases.
Adjusted variable names in GetAndGetAllWithNullableValues and GetAsyncAndGetAllAsyncWithNullableValues.

* Changed IUserWithNullableDob to INullableDate.

* fix Insert<T> when T is declared as IEnumerable<T> (#948)

* Removing unjustified use of AppendFormat in StringBuilder class (#989)

* Remove reference to Stack Overflow docs 

Should resolve #992

* Better error messages for .*Async methods when not using  DbConnection (#986)

* Better error messages for .*Async methods when not using  DbConnection

Perhaps in v2 we move these to DbConnection itself ratherr than IDbConnection for the extensions to eliminate the case, but that's breaking...for now we can at least throw a better error. See #757 for details.

* Tweak errors to allow open IDbConnections and those generating DbCommands

Same checks but a bit more lenient with more specific messaging.

* Tweaking error messages and supporting IDbConnection implementations … (#987)

* Fixed dead link in Readme.md

Replaced a dead link in Readme.md by a link to the WaybackMachine

* Readme.md misc tidying
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment