{"id":23138136,"url":"https://github.com/roman-koshchei/unator","last_synced_at":"2025-08-21T18:10:30.113Z","repository":{"id":156285402,"uuid":"626920207","full_name":"roman-koshchei/unator","owner":"roman-koshchei","description":"C# utilities, such as typesafe router. Breaking harmful standards is fine.","archived":false,"fork":false,"pushed_at":"2024-08-12T13:08:03.000Z","size":20050,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-09T20:26:27.514Z","etag":null,"topics":["breaking-standards","csharp","entity-framework-core","utilities","utils"],"latest_commit_sha":null,"homepage":"https://roman-koshchei.github.io/unator","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/roman-koshchei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-12T12:28:16.000Z","updated_at":"2024-08-12T13:08:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"601dfb2b-299e-4b1d-a603-7f8770e8a390","html_url":"https://github.com/roman-koshchei/unator","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-koshchei%2Funator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-koshchei%2Funator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-koshchei%2Funator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-koshchei%2Funator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roman-koshchei","download_url":"https://codeload.github.com/roman-koshchei/unator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247157132,"owners_count":20893210,"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":["breaking-standards","csharp","entity-framework-core","utilities","utils"],"created_at":"2024-12-17T13:09:53.135Z","updated_at":"2025-04-04T09:43:55.530Z","avatar_url":"https://github.com/roman-koshchei.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"![unator banner](./assets/unator-banner.png)\n\n# Unator\n\nBreaking mistaken standards of enterprise such as Repository pattern.\nMy goal is to provide a set of functions/classes to make development transparent and logical.\n\n1. [Database](#database--entity-framework-core)\n2. [Environment variables](#environment-variables)\n3. [Emails](#emails)\n4. [Storage](#storage)\n\nCheck later: [github.com/BinaryBirds/swift-html](https://github.com/BinaryBirds/swift-html)\n\n## Database / Entity Framework Core\n\nProbably you use Entity Framework Core to access database. I do so.\nBut you may be taught to use `Repository` pattern and throw exceptions. Not anymore!\nI see too few benefits to add complexity of Repository.\n\nSo we will use just few generic extensions for database. And our code will look like this:\n\n### Querying data\n\n```csharp\nvar products = await db.Products\n  .Where(x =\u003e x.Price \u003c 100)\n  .Select(x =\u003e new { x.Id, x.Title })\n  .QueryMany();\n\nvar product = await db.Products\n  .Select(x =\u003e new { x.Id, x.Title })\n  .QueryOne(x =\u003e x.Id == 51);\n```\n\n`QueryMany` and `QueryOne` allow to get data. You can pass where condition right into function or do it before. Both functions are configured with `ConfigureAwait(false)`. When you query one entity it returns null if entity isn't found.\n\nThe benefit is you remove complexity and query minimal amount of data by using `Select`.\n\n### Modifying data\n\n```csharp\nvar product = new Product(\"Title for new product\");\nawait db.Products.AddAsync(product)\nvar saved = await db.Save();\n```\n\n`Save` for DbContext allow us to save changes to the database without throwing exceptions. It just returns `true` if changes saved successfully otherwise `false`.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froman-koshchei%2Funator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froman-koshchei%2Funator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froman-koshchei%2Funator/lists"}