{"id":16678935,"url":"https://github.com/joncloud/sage-net","last_synced_at":"2026-05-07T01:05:45.312Z","repository":{"id":31237021,"uuid":"127316809","full_name":"joncloud/sage-net","owner":"joncloud","description":"Cross platform app that hashes mssql query results for testing","archived":false,"fork":false,"pushed_at":"2024-03-29T04:35:21.000Z","size":67,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"publish","last_synced_at":"2025-07-26T12:34:50.588Z","etag":null,"topics":["hash","json","mssql","query","test"],"latest_commit_sha":null,"homepage":"","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/joncloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2018-03-29T16:16:14.000Z","updated_at":"2024-03-29T04:35:25.000Z","dependencies_parsed_at":"2024-10-12T13:32:24.426Z","dependency_job_id":"7a85af12-3475-4a6d-a3f3-bc3d9922a09a","html_url":"https://github.com/joncloud/sage-net","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/joncloud/sage-net","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joncloud%2Fsage-net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joncloud%2Fsage-net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joncloud%2Fsage-net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joncloud%2Fsage-net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joncloud","download_url":"https://codeload.github.com/joncloud/sage-net/tar.gz/refs/heads/publish","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joncloud%2Fsage-net/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268177804,"owners_count":24208394,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["hash","json","mssql","query","test"],"created_at":"2024-10-12T13:32:20.176Z","updated_at":"2026-05-07T01:05:45.285Z","avatar_url":"https://github.com/joncloud.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sage.NET\r\n[![NuGet](https://img.shields.io/nuget/v/sage.svg)](https://www.nuget.org/packages/sage/)\r\n![.NET Core](https://github.com/joncloud/sage-net/workflows/.NET%20Core/badge.svg)\r\n[![BuiltWithDot.Net shield](https://builtwithdot.net/project/489/sage-global-tool/badge)](https://builtwithdot.net/project/489/sage-global-tool)\r\n\r\n## Description\r\nSage.NET queries SQL Server databases and converts results into a hash.\r\n\r\n## Licensing\r\nReleased under the MIT License.  See the [LICENSE][] file for further details.\r\n\r\n[license]: LICENSE.md\r\n\r\n## Installation\r\nInstall `https` as a global .NET tool using\r\n```bash\r\ndotnet tool install --global sage --version 0.4.1\r\n```\r\n\r\n## Usage\r\nSage.NET accepts several different ways to represent queries, executes them, and then hashes all of the results.\r\n\r\n### Simple Query\r\nA single query can be executed with a simple string. These will be named `Query`.\r\n```powershell\r\n$Query = \"SELECT 1 [Num]\" | ConvertTo-Json\r\n$ConnectionString = \"Data Source=.;Initial Catalog=master;Integrated Security=true;\"\r\n$Query | sage tab $ConnectionString\r\nQuery  0x313EA196881D370AEEAF78E274B0D08541F6CBF0DDFC7BE57A4594AD0A752A5C\r\n```\r\n\r\n### Named Query\r\nA single query can also be run by creating a JSON object with a name property.\r\n```powershell\r\n$Query = @{\r\n  name = \"Query\";\r\n  commandText = \"SELECT 1 [Num]\"\r\n}\r\n$Json = $Query | ConvertTo-Json\r\n$ConnectionString = \"Data Source=.;Initial Catalog=master;Integrated Security=true;\"\r\n$Json | sage tab $ConnectionString\r\nQuery  0x313EA196881D370AEEAF78E274B0D08541F6CBF0DDFC7BE57A4594AD0A752A5C\r\n```\r\n\r\n### Multiple Queries\r\nRun multiple queries by creating an array of named queries.\r\n```powershell\r\n$Queries = @(\r\n  @{\r\n    name = \"Query1\";\r\n    commandText = \"SELECT 1 [Num]\"\r\n  },\r\n  @{\r\n    name = \"Query2\";\r\n    commandText = \"SELECT 2 [Num]\"\r\n  }\r\n)\r\n$Json = $Queries | ConvertTo-Json\r\n$ConnectionString = \"Data Source=.;Initial Catalog=master;Integrated Security=true;\"\r\n$Json | sage tab $ConnectionString\r\nQuery1  0x313EA196881D370AEEAF78E274B0D08541F6CBF0DDFC7BE57A4594AD0A752A5C\r\nQuery2  0x54CB67D1746CD42CA947F6CE705060D0FB5540E55D588F5726CDAD0B73F41618\r\n```\r\n\r\nUse the `--hash` flag to change the hashing algorithm. By default Sage uses `SHA256`. Sage supports\r\n * MD5\r\n * SHA1\r\n * SHA256\r\n * SHA384\r\n * SHA512\r\n```powershell\r\n$Json | sage tab $ConnectionString --hash=MD5\r\nQuery1  0xF851F5BA5DEB579BBFE5D98E9CD268F6\r\nQuery2  0x048F9E6DEF2045421BC057264C16A042\r\n```\r\n\r\nUse the `--out-dir` flag in order to persist the information from the resulting query.\r\n```powershell\r\n$Json | sage tab $ConnectionString --out-dir=./\r\n...\r\nGet-Content ./Query1\r\n1\r\nGet-Content ./Query2\r\n2\r\n```\r\n\r\nUse the `json` command to export the information as JSON instead of Tab-Delimited. Note that the hashes produced by JSON output vary from the Tab-Delimited output.\r\n```powershell\r\n$Json | sage json $ConnectionString --out-dir=./\r\n...\r\nGet-Content ./Query1\r\n[\r\n  {\r\n    \"Num\":1\r\n\r\n  }\r\n]\r\nGet-Content ./Query2\r\n[\r\n  {\r\n    \"Num\":2\r\n\r\n  }\r\n]\r\n```\r\n\r\nSage.NET will also report exceptions from query execution:\r\n```powershell\r\n$Query = @{\r\n  name = \"Query\";\r\n  commandText = \"SELECT x [Num]\"\r\n}\r\n$Json = $Query | ConvertTo-Json\r\n$ConnectionString = \"Data Source=.;Initial Catalog=master;Integrated Security=true;\"\r\n$Json | sage tab $ConnectionString\r\nQuery  System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'x'.\r\n   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)\r\n   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)\r\n   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)\r\n   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean\u0026 dataReady)\r\n   at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()\r\n   at System.Data.SqlClient.SqlDataReader.get_MetaData()\r\n   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)\r\n   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task\u0026 task, Boolean asyncWrite, SqlDataReader ds)\r\n   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task\u0026 task, Boolean asyncWrite, String method)\r\n   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)\r\n   at System.Data.SqlClient.SqlCommand.ExecuteReader()\r\n   at Sage.Formatters.ReadDataTabDelimited(SqlCommand command, StreamWriter writer) in ./src/Sage/Formatters.cs:line 16\r\n   at Sage.Program.LoadData(String connectionString, String file, String commandText, Formatter fn) in ./src/Sage/Program.cs:line 210\r\n   at Sage.Program.ComputeHash(String connectionString, String name, String commandText, OutDir outDir, Formatter fn, HashAlgorithm algorithm) in ./src/Sage/Program.cs:line 180\r\n   at Rlx.Functions.\u003c\u003ec__DisplayClass35_0`7.\u003cTry\u003eb__0()\r\n   at Rlx.Attempt`1.Catch[TException]()\r\nClientConnectionId:f6663cff-34f2-49ba-8cad-326f3be6af17\r\nError Number:207,State:1,Class:16\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoncloud%2Fsage-net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoncloud%2Fsage-net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoncloud%2Fsage-net/lists"}