{"id":19101884,"url":"https://github.com/tmenier/AsyncPoco","last_synced_at":"2025-04-18T19:31:09.953Z","repository":{"id":2258223,"uuid":"3213777","full_name":"tmenier/AsyncPoco","owner":"tmenier","description":"A long-\"awaited\" fully asynchronous PetaPoco fork","archived":false,"fork":true,"pushed_at":"2024-01-21T23:38:09.000Z","size":1410,"stargazers_count":128,"open_issues_count":10,"forks_count":33,"subscribers_count":22,"default_branch":"master","last_synced_at":"2024-05-06T09:34:11.387Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"CollaboratingPlatypus/PetaPoco","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmenier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-01-19T00:02:49.000Z","updated_at":"2023-08-04T10:11:00.000Z","dependencies_parsed_at":"2023-07-05T18:01:37.174Z","dependency_job_id":null,"html_url":"https://github.com/tmenier/AsyncPoco","commit_stats":{"total_commits":257,"total_committers":16,"mean_commits":16.0625,"dds":"0.31906614785992216","last_synced_commit":"7311f4c70b7bb2df518accfbf0d9871a7e65b33b"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmenier%2FAsyncPoco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmenier%2FAsyncPoco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmenier%2FAsyncPoco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmenier%2FAsyncPoco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmenier","download_url":"https://codeload.github.com/tmenier/AsyncPoco/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223783195,"owners_count":17201912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T03:53:31.097Z","updated_at":"2025-04-18T19:31:09.927Z","avatar_url":"https://github.com/tmenier.png","language":"C#","readme":"# AsyncPoco\n\n***2.0 is here! For details and help transitioning from 1.x, check out the [upgrade guide](https://github.com/tmenier/AsyncPoco/wiki/2.0-Upgrade-Guide).***\n\nAsyncPoco is a fork of the popular PetaPoco micro-ORM for .NET, with a fully asynchronous API and broad cross-platform support, including .NET Core. If you're familiar with PetaPoco and the [TAP pattern](http://msdn.microsoft.com/en-us/library/hh873175.aspx) (i.e. `async`/`await`), the transition to AsyncPoco should be quite intuitive.\n\n```C#\nvar db = new AsyncPoco.Database(\"connectionStringName\");\n\nvar count = await db.ExecuteScalarAsync\u003clong\u003e(\"SELECT Count(*) FROM articles\");\nvar a = await db.SingleOrDefaultAsync\u003cArticle\u003e(\"SELECT * FROM articles WHERE article_id = @0\", 123);\nvar result = await db.PageAsync\u003cArticle\u003e(1, 20, // \u003c-- page number and items per page\n        \"SELECT * FROM articles WHERE category = @0 ORDER BY date_posted DESC\", \"coolstuff\");\n\nawait db.ExecuteAsync(\"DELETE FROM articles WHERE draft\u003c\u003e0\");\nawait db.DeleteAsync\u003cArticle\u003e(\"WHERE article_id = @0\", 123);\nawait db.UpdateAsync\u003cArticle\u003e(\"SET title = @0 WHERE article_id = @1\", \"New Title\", 123);\nawait db.SaveAsync(a);\n```\n\nOne imporant note is that **the constructor in the example above is not supported in .NET Core**. In a config file, a connection string generally includes a `providerName`, which resolves to a globally registered ADO.NET provider. Unfortunately, this functionality is absent in .NET Core, so AsyncPoco requires that you pass the provider a bit more directly. This is still pretty painless; either of these will work:\n\n```c#\nvar db = Database.Create\u003cMySqlConnection\u003e(\"connectionString\");\nvar db = Database.Create(() =\u003e new OracleConnection(\"connectionString\"));\n```\n\nOne case where the transition to AsyncPoco might be less straightforward is the `Query` method. In PetaPoco, `Query\u003cT\u003e` (and its various overloads) returns `IEnumerable\u003cT\u003e`, and its implementation `yield return`s POCOs as it streams results from the underlying DataReader. But AsyncPoco's `QueryAsync\u003cT\u003e` methods do not return `Task\u003cIEnumerable\u003cT\u003e\u003e`. The reason is that if you `await` a method with that signature, you will not have results to work with until the `Task` completes, meaning all results are pulled into memory, at which point you may as well `Fetch` a `List\u003cT\u003e`. Ideally, you want to be able to process the results asynchronously *as they become available*. So instead of returning a result that can be enumerated, `QueryAsync\u003cT\u003e` accepts a callback that is invoked for each POCO in the result set as it becomes available.\n\n```C#\nawait db.QueryAsync\u003cArticle\u003e(\"SELECT * FROM articles\", a =\u003e\n{\n    Console.WriteLine(\"{0} - {1}\", a.article_id, a.title);\n});\n```\n\nWhat if you want to stop processing results before you reach the end of the DataReader's stream? There is a set of `QueryAsync\u003cT\u003e` overloads that take a `Func\u003cT, bool\u003e` callback; simply return `false` from the callback to hault the iteration immediately and close/dispose the `DataReader`.\n\n```C#\nawait db.QueryAsync\u003cArticle\u003e(\"SELECT * FROM articles\", a =\u003e\n{\n    if (IsWhatIWant(a))\n    {\n        Console.WriteLine(\"Found it! {0} - {1}\", a.article_id, a.title);\n        return false; // stop iterating and close/dispose the DataReader\n    }\n    else\n    {\n        return true; // continue iterating\n    }\n});\n```\n\n## What databases are supported?\n\nAsyncPoco supports the following database platforms:\n\n- SQL Server\n- Oracle\n- MySQL\n- PostgreSQL\n- SQLite\n- SQL Server CE\n\n## What flavors of .NET are supported?\n\nAsyncPoco targets full .NET Framework as well as .NET Standard 1.3 and 2.0, meaning it will run on the following platforms:\n\n- .NET Framework 4.5 and above\n- .NET Core 1.0 and 2.0\n- Mono\n- Xamarin.iOS\n- Xamarin.Mac\n- Xamarin.Android\n- UWP (Windows 10)\n\n## Is it faster than PetaPoco?\n\nNo. But that's not the point of asynchronous code. The point is to free up threads while waiting on I/O-bound work to complete, making desktop and mobile apps more responsive and web applications more scalable.\n\n## Why *shouldn't* I switch from PetaPoco?\n\nOnce you start converting synchronous code to async, it's said to spread like a zombie virus, meaning that if you're dealing with a large codebase, be prepared to make a substantial number of changes. If don't have the time or resources needed for this commitment, AsyncPoco is probably not a good fit. Going only partially async is an [invitation for deadlocks](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html). A good rule of thumb is if you've used `.Wait()` or `.Result` anywhere in your code (other than perhaps the `Main` method of a console app), you've done something wrong. You need to either use async all the way up and down your call stack, or not at all.\n\n## Where do I get it?\n\nAsyncPoco is available via [NuGet](https://www.nuget.org/packages/AsyncPoco/):\n\n`PM\u003e Install-Package AsyncPoco`\n\n## How do I get help?\n\n- Ask specific programming questions on [Stack Overflow](http://stackoverflow.com/questions/ask?tags=asyncpoco+c%23+orm+micro-orm+async-await). I'll answer personally (unless someone beats me to it).\n- For announcements and (light) discussions, follow [@AsyncPoco](https://twitter.com/AsyncPoco) on Twitter.\n- To report bugs or suggest improvements, no matter how opinionated, [create an issue](https://github.com/tmenier/AsyncPoco/issues/new).\n\n## How can I contribute?\n\nI'll gladly accept pull requests that address issues and implement cool features, although I generally prefer that you [create an issue](https://github.com/tmenier/AsyncPoco/issues/new) first so we can discuss the specifics. I'd also be grateful for your help spreading the word via [Twitter](https://twitter.com/intent/tweet?text=Check%20out%20AsyncPoco!\u0026tw_p=tweetbutton\u0026url=https%3A%2F%2Fgithub.com%2Ftmenier%2FAsyncPoco), blog posts, etc.\n\n## Credit where credit is due\n\nWell over 90% of this code is the brainchild of Brad Robinson ([@toptensoftware](https://twitter.com/toptensoftware)); I'm merely riding the coattails of [PetaPoco](http://www.toptensoftware.com/petapoco)'s success. Brad in turn credits Rob Conery ([@robconery](https://twitter.com/robconery)) for original inspiration (ie: [Massive](https://github.com/robconery/massive)), Rob Sullivan ([@DataChomp](https://twitter.com/DataChomp)) for hard core DBA advice, and Adam Schroder ([@schotime](https://twitter.com/schotime)) for lots of suggestions, improvements and Oracle support.\n","funding_links":[],"categories":["others","C\\#","ORM","C# #"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmenier%2FAsyncPoco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmenier%2FAsyncPoco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmenier%2FAsyncPoco/lists"}