{"id":20905181,"url":"https://github.com/akkadotnet/akka.persistence.sqlserver","last_synced_at":"2025-03-25T03:13:31.756Z","repository":{"id":32422738,"uuid":"36000108","full_name":"akkadotnet/Akka.Persistence.SqlServer","owner":"akkadotnet","description":"Akka.Persistence.SqlServer provider","archived":false,"fork":false,"pushed_at":"2025-01-23T20:33:18.000Z","size":6527,"stargazers_count":59,"open_issues_count":11,"forks_count":50,"subscribers_count":16,"default_branch":"dev","last_synced_at":"2025-03-18T02:09:48.226Z","etag":null,"topics":["akkadotnet","mssql","sql"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akkadotnet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"2015-05-21T08:16:00.000Z","updated_at":"2025-01-23T20:27:31.000Z","dependencies_parsed_at":"2023-02-17T07:00:41.722Z","dependency_job_id":"288e5e2a-176c-4f7d-b33a-0d917749b480","html_url":"https://github.com/akkadotnet/Akka.Persistence.SqlServer","commit_stats":{"total_commits":238,"total_committers":32,"mean_commits":7.4375,"dds":0.7394957983193278,"last_synced_commit":"b730585b2af64eea9141f3ae84b8d5d5e90dde93"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FAkka.Persistence.SqlServer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FAkka.Persistence.SqlServer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FAkka.Persistence.SqlServer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akkadotnet%2FAkka.Persistence.SqlServer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akkadotnet","download_url":"https://codeload.github.com/akkadotnet/Akka.Persistence.SqlServer/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245388782,"owners_count":20607165,"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":["akkadotnet","mssql","sql"],"created_at":"2024-11-18T13:22:56.601Z","updated_at":"2025-03-25T03:13:31.747Z","avatar_url":"https://github.com/akkadotnet.png","language":"C#","readme":"# Deprecation Notice: Akka.Persistence.SqlServer\n\n\u003e [!WARNING]\n\u003e\n\u003e All Akka.Persistence plugins based on the `Akka.Persistence.Sql.Common` package are now **deprecated**. We strongly recommend that you migrate to the new [`Akka.Persistence.Sql` or the `Akka.Persistence.Sql.Hosting`](https://github.com/akkadotnet/Akka.Persistence.Sql) package.\n\n## Migration Resources\n\nTo assist with the migration, please refer to the following resources:\n\n- **Migration Guide:**  \n  Learn the necessary steps to upgrade by following the [Migration Guide](https://github.com/akkadotnet/Akka.Persistence.Sql/blob/dev/docs/articles/migration.md).\n\n- **Migration Walkthrough:**  \n  For a step-by-step walkthrough, check out our [Migration Walkthrough](https://github.com/akkadotnet/Akka.Persistence.Sql/blob/dev/docs/articles/migration-walkthrough.md).\n\n- **Migration Guide Video:**  \n  Watch the [Migration Guide Video](https://www.youtube.com/watch?v=gSmqUrVHPq8) on YouTube for a detailed explanation of the migration process.\n\n---\n\n# Akka.Persistence.SqlServer\n\nAkka Persistence journal and snapshot store backed by SQL Server database.\n\n### Configuration\n\nBoth journal and snapshot store share the same configuration keys (however they resides in separate scopes, so they are\ndefinied distinctly for either journal or snapshot store):\n\nRemember that connection string must be provided separately to Journal and Snapshot Store.\n\nPlease also note that unless circuit breaker settings are configured, the defaults from Akka.Persistence will be used.\nIf these defaults are less than the Database connection timeout (default or provided in connection string) and provided\ncommand timeout, Warnings will be logged upon initialization of the Journal or Snapshot Store.\n\n```hocon\nakka.persistence{\n\tjournal {\n\t        plugin = \"akka.persistence.journal.sql-server\"\n\t\tsql-server {\n\t\t\t# qualified type name of the SQL Server persistence journal actor\n\t\t\tclass = \"Akka.Persistence.SqlServer.Journal.SqlServerJournal, Akka.Persistence.SqlServer\"\n\n\t\t\t# dispatcher used to drive journal actor\n\t\t\tplugin-dispatcher = \"akka.actor.default-dispatcher\"\n\n\t\t\t# connection string used for database access\n\t\t\tconnection-string = \"\"\n\n\t\t\t# default SQL commands timeout\n\t\t\tconnection-timeout = 30s\n\n\t\t\t# SQL server schema name to table corresponding with persistent journal\n\t\t\tschema-name = dbo\n\n\t\t\t# SQL server table corresponding with persistent journal\n\t\t\ttable-name = EventJournal\n\n\t\t\t# should corresponding journal table be initialized automatically\n\t\t\tauto-initialize = off\n\n\t\t\t# timestamp provider used for generation of journal entries timestamps\n\t\t\ttimestamp-provider = \"Akka.Persistence.Sql.Common.Journal.DefaultTimestampProvider, Akka.Persistence.Sql.Common\"\n\n\t\t\t# metadata table\n\t\t\tmetadata-table-name = Metadata\n\t\t\t\n\t\t\t# Recommended: change default circuit breaker settings\n\t\t\t# By uncommenting below and using Connection Timeout + Command Timeout\n\t\t\t# circuit-breaker.call-timeout=30s\n\t\t}\n\t}\n\n\tsnapshot-store {\n\t        plugin = \"akka.persistence.snapshot-store.sql-server\"\n\t\tsql-server {\n\n\t\t\t# qualified type name of the SQL Server persistence journal actor\n\t\t\tclass = \"Akka.Persistence.SqlServer.Snapshot.SqlServerSnapshotStore, Akka.Persistence.SqlServer\"\n\n\t\t\t# dispatcher used to drive journal actor\n\t\t\tplugin-dispatcher = \"\"akka.actor.default-dispatcher\"\"\n\n\t\t\t# connection string used for database access\n\t\t\tconnection-string = \"\"\n\n\t\t\t# default SQL commands timeout\n\t\t\tconnection-timeout = 30s\n\n\t\t\t# SQL server schema name to table corresponding with persistent journal\n\t\t\tschema-name = dbo\n\n\t\t\t# SQL server table corresponding with persistent journal\n\t\t\ttable-name = SnapshotStore\n\n\t\t\t# should corresponding journal table be initialized automatically\n\t\t\tauto-initialize = off\n\t\t\t\n\t\t\t# Recommended: change default circuit breaker settings\n\t\t\t# By uncommenting below and using Connection Timeout + Command Timeout\n\t\t\t# circuit-breaker.call-timeout=30s\n\t\t}\n\t}\n}\n```\n\n### Batching journal\n\nSince version 1.1.3 an alternative, experimental type of the journal has been released, known as batching journal. It's\noptimized for concurrent writes made by multiple persistent actors, thanks to the ability of batching multiple SQL\noperations to be executed within the same database connection. In some of those situations we've noticed over an order\nof magnitude in event write speed.\n\nTo use batching journal, simply change `akka.persistence.journal.sql-server.class` to\n*Akka.Persistence.SqlServer.Journal.BatchingSqlServerJournal, Akka.Persistence.SqlServer*.\n\nAdditionally to the existing settings, batching journal introduces few more:\n\n- `isolation-level` to define isolation level for transactions used withing event reads/writes. Possible options:\n  *unspecified* (default), *chaos*, *read-committed*, *read-uncommitted*, *repeatable-read*, *serializable* or\n  *snapshot*.\n- `max-concurrent-operations` is used to limit the maximum number of database connections used by this journal. You can\n  use them in situations when you want to partition the same ADO.NET pool between multiple components. Current default:\n  *64*.\n- `max-batch-size` defines the maximum number of SQL operations, that are allowed to be executed using the same\n  connection. When there are more operations, they will chunked into subsequent connections. Current default: *100*.\n- `max-buffer-size` defines maximum buffer capacity for the requests send to a journal. Once buffer gets overflown, a\n  journal will call `OnBufferOverflow` method. By default it will reject all incoming requests until the buffer space\n  gets freed. You can inherit from `BatchingSqlServerJournal` and override that method to provide a custom backpressure\n  strategy. Current default: *500 000*.\n\n### Table Schema\n\nSQL Server persistence plugin defines a default table schema used for journal, snapshot store and metadata table.\n\n```SQL\nCREATE TABLE {your_journal_table_name} (\n  Ordering BIGINT IDENTITY(1,1) NOT NULL,\n  PersistenceID NVARCHAR(255) NOT NULL,\n  SequenceNr BIGINT NOT NULL,\n  Timestamp BIGINT NOT NULL,\n  IsDeleted BIT NOT NULL,\n  Manifest NVARCHAR(500) NOT NULL,\n  Payload VARBINARY(MAX) NOT NULL,\n  Tags NVARCHAR(100) NULL,\n  SerializerId INTEGER NULL\n  CONSTRAINT PK_{your_journal_table_name} PRIMARY KEY (Ordering),\n  CONSTRAINT QU_{your_journal_table_name} UNIQUE (PersistenceID, SequenceNr)\n);\n\nCREATE TABLE {your_snapshot_table_name} (\n  PersistenceID NVARCHAR(255) NOT NULL,\n  SequenceNr BIGINT NOT NULL,\n  Timestamp DATETIME2 NOT NULL,\n  Manifest NVARCHAR(500) NOT NULL,\n  Snapshot VARBINARY(MAX) NOT NULL,\n  SerializerId INTEGER NULL\n  CONSTRAINT PK_{your_snapshot_table_name} PRIMARY KEY (PersistenceID, SequenceNr)\n);\n\nCREATE TABLE {your_metadata_table_name} (\n  PersistenceID NVARCHAR(255) NOT NULL,\n  SequenceNr BIGINT NOT NULL,\n  CONSTRAINT PK_{your_metadata_table_name} PRIMARY KEY (PersistenceID, SequenceNr)\n);\n```\n\nUnderneath Akka.Persistence.SqlServer uses a raw ADO.NET commands. You may choose not to use a dedicated built in ones,\nbut to create your own being better fit for your use case. To do so, you have to create your own versions\nof `IJournalQueryBuilder` and `IJournalQueryMapper` (for custom journals) or `ISnapshotQueryBuilder`\nand `ISnapshotQueryMapper` (for custom snapshot store) and then attach inside journal, just like in the example below:\n\n```C#\nclass MyCustomSqlServerJournal: Akka.Persistence.SqlServer.Journal.SqlServerJournal\n{\n    public MyCustomSqlServerJournal() : base()\n    {\n        QueryBuilder = new MyCustomJournalQueryBuilder();\n        QueryMapper = new MyCustomJournalQueryMapper();\n    }\n}\n```\n\n### Migration\n\n#### From 1.1.2 to 1.3.1\n\n```sql\nALTER TABLE {your_journal_table_name} ADD COLUMN SerializerId INTEGER NULL\nALTER TABLE {your_snapshot_table_name} ADD COLUMN SerializerId INTEGER NULL\n```\n\n#### From 1.1.0 to 1.1.2\n\n```sql\nALTER TABLE {your_journal_table_name} DROP CONSTRAINT PK_{your_journal_table_name};\nALTER TABLE {your_journal_table_name} ADD Ordering BIGINT IDENTITY(1,1) PRIMARY KEY NOT NULL;\nALTER TABLE {your_journal_table_name} ADD Ordering BIGINT IDENTITY(1,1) NOT NULL;\nALTER TABLE {your_journal_table_name} ADD CONSTRAINT PK_EventJournal PRIMARY KEY (Ordering);\nALTER TABLE {your_journal_table_name} ADD CONSTRAINT QU_{your_journal_table_name} UNIQUE (PersistenceID, SequenceNr);\n```\n\n#### From 1.0.8 to 1.1.0\n\n```SQL\n-- helper function to convert between DATETIME2 and BIGINT as .NET ticks\n-- taken from: http://stackoverflow.com/questions/7386634/convert-sql-server-datetime-object-to-bigint-net-ticks\nCREATE FUNCTION [dbo].[Ticks] (@dt DATETIME)\nRETURNS BIGINT\nWITH SCHEMABINDING\nAS\nBEGIN\nDECLARE @year INT = DATEPART(yyyy, @dt)\nDECLARE @month INT = DATEPART(mm, @dt)\nDECLARE @day INT = DATEPART(dd, @dt)\nDECLARE @hour INT = DATEPART(hh, @dt)\nDECLARE @min INT = DATEPART(mi, @dt)\nDECLARE @sec INT = DATEPART(ss, @dt)\n\nDECLARE @days INT =\n    CASE @month - 1\n        WHEN 0 THEN 0\n        WHEN 1 THEN 31\n        WHEN 2 THEN 59\n        WHEN 3 THEN 90\n        WHEN 4 THEN 120\n        WHEN 5 THEN 151\n        WHEN 6 THEN 181\n        WHEN 7 THEN 212\n        WHEN 8 THEN 243\n        WHEN 9 THEN 273\n        WHEN 10 THEN 304\n        WHEN 11 THEN 334\n        WHEN 12 THEN 365\n    END\n    IF  @year % 4 = 0 AND (@year % 100  != 0 OR (@year % 100 = 0 AND @year % 400 = 0)) AND @month \u003e 2 BEGIN\n        SET @days = @days + 1\n    END\nRETURN CONVERT(bigint,\n    ((((((((@year - 1) * 365) + ((@year - 1) / 4)) - ((@year - 1) / 100)) + ((@year - 1) / 400)) + @days) + @day) - 1) * 864000000000) +\n    ((((@hour * 3600) + CONVERT(bigint, @min) * 60) + CONVERT(bigint, @sec)) * 10000000) + (CONVERT(bigint, DATEPART(ms, @dt)) * CONVERT(bigint,10000));\n\nEND;\nALTER TABLE {your_journal_table_name} ADD Timestamp_tmp BIGINT NULL;\nUPDATE {your_journal_table_name} SET Timestamp_tmp = dbo.Ticks(Timestamp);\nDROP INDEX [IX_EventJournal_Timestamp] ON {your_journal_table_name};\nALTER TABLE {your_journal_table_name} DROP COLUMN Timestamp;\nALTER TABLE {your_journal_table_name} ALTER COLUMN Timestamp_tmp BIGINT NOT NULL;\nEXEC sp_RENAME '{your_journal_table_name}.Timestamp_tmp' , 'Timestamp', 'COLUMN';\nCREATE NONCLUSTERED INDEX [IX_EventJournal_Timestamp] ON {your_journal_table_name}([Timestamp] ASC);\nALTER TABLE {your_journal_table_name} ADD Tags NVARCHAR(100) NULL;\n```\n\n#### From 1.0.6 to 1.0.8\n\n```SQL\nCREATE TABLE {your_metadata_table_name} (\n  PersistenceID NVARCHAR(255) NOT NULL,\n  SequenceNr BIGINT NOT NULL,\n  CONSTRAINT PK_Metadata PRIMARY KEY (PersistenceID, SequenceNr)\n);\n\nINSERT INTO {your_metadata_table_name} (PersistenceID, SequenceNr)\nSELECT PersistenceID, MAX(SequenceNr) as SequenceNr FROM {your_journal_table_name} GROUP BY PersistenceID;\n\nALTER TABLE {your_journal_table_name} ALTER COLUMN PersistenceID NVARCHAR(255) [NOT NULL];\n```\n\n#### From 1.0.4 to 1.0.5\n\n```SQL\nALTER TABLE dbo.EventJournal ADD Timestamp DATETIME2 NOT NULL DEFAULT GETDATE();\nALTER TABLE dbo.EventJournal DROP CONSTRAINT PK_EventJournal;\nALTER TABLE dbo.EventJournal DROP COLUMN CS_PID;\nALTER TABLE dbo.EventJournal ADD CONSTRAINT PK_EventJournal PRIMARY KEY (PersistenceID, SequenceNr);\nsp_RENAME 'EventJournal.PayloadType', 'Manifest', 'COLUMN';\nsp_RENAME 'SnapshotStore.PayloadType', 'Manifest', 'COLUMN';\n```\n\n### Tests\n\nThe SqlServer tests are packaged and run as part of the default \"All\" build task.\n\nIn order to run the tests, you must do the following things:\n\n1. Download and install SQL Server Express 2014\n   from: http://www.microsoft.com/en-us/server-cloud/Products/sql-server-editions/sql-server-express.aspx\n2. Install SQL Server Express with the default settings.\n3. Create a new user called `akkadotnet` with the password `akkadotnet` and give them rights to create new databases on\n   the server.\n4. The default connection string uses the following\n   credentials: `Data Source=localhost\\SQLEXPRESS;Database=akka_persistence_tests;User Id=akkadotnet;\n   Password=akkadotnet;`\n5. A custom app.config file can be used and needs to be placed in the same folder as the dll\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakkadotnet%2Fakka.persistence.sqlserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakkadotnet%2Fakka.persistence.sqlserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakkadotnet%2Fakka.persistence.sqlserver/lists"}