﻿
{"id":21574,"date":"2021-05-09T05:47:02","date_gmt":"2021-05-09T05:47:02","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=21574"},"modified":"2021-05-09T14:49:29","modified_gmt":"2021-05-09T14:49:29","slug":"net-core-ortaminda-event-store-ile-event-sourcing-yapilanmasi","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/net-core-ortaminda-event-store-ile-event-sourcing-yapilanmasi\/","title":{"rendered":".NET Core Ortam\u0131nda &#8216;Event Store&#8217; \u0130le Event Sourcing Yap\u0131lanmas\u0131"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bir \u00f6nceki <a href=\"https:\/\/www.gencayyildiz.com\/blog\/basit-bir-event-sourcing-uygulamasi-gelistirelim\/\" rel=\"noopener\" target=\"_blank\">Basit Bir Event Sourcing Uygulamas\u0131 Geli\u015ftirelim<\/a> ba\u015fl\u0131kl\u0131 makalemizde <a href=\"https:\/\/www.gencayyildiz.com\/blog\/event-sourcing-nedir-haydi-gelin-hep-beraber-inceleyelim\/\" rel=\"noopener\" target=\"_blank\">Event Sourcing<\/a> pattern&#8217;\u0131n\u0131n nas\u0131l ger\u00e7ekle\u015ftirilebildi\u011fine pratiksel olarak bir \u00f6rnek vermeye \u00e7al\u0131\u015fm\u0131\u015ft\u0131k. \u0130lgili makalede ele al\u0131nan \u00f6rnekten de g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere uygulamada ger\u00e7ekle\u015ftirilen &#8216;event&#8217;lerin in-memory&#8217;de depolanmas\u0131 yerine daha y\u00f6netilebilir bir vaziyette olmas\u0131 i\u00e7in veritaban\u0131nda yahut bu ama\u00e7la geli\u015ftirilmi\u015f \u00f6zel tool&#8217;lar da tutulmas\u0131 daha elveri\u015fli olacak kanaatindeyiz. Dolay\u0131s\u0131yla bu i\u00e7eri\u011fimizde Event Sourcing pattern&#8217;\u0131n\u0131 uygulayabilmek i\u00e7in geli\u015ftirilmi\u015f olan &#8216;Event Store&#8217; tool&#8217;unu sizlerle tan\u0131\u015ft\u0131racak ve bir\u00e7ok nimetinden haberdar olup, istifade ediyor olaca\u011f\u0131z.<\/p>\n<h6>Event Store Nedir?<\/h6>\n<p>Event Store, Event Sourcing i\u00e7in geli\u015ftirilmi\u015f olan event&#8217;leri depolamam\u0131z\u0131 sa\u011flayan ve bununla birlikte &#8216;Read\/Query&#8217; veritabanlar\u0131na kay\u0131t atabilmek i\u00e7in dahili bir &#8216;Message Broker&#8217; hizmeti sa\u011flayan Open Source bir veritaban\u0131d\u0131r. HTTP ve TCP protokollerini desteklemektedir.<\/p>\n<h6>Hangi Protokol\u00fc Tercih Edilmelidir?<\/h6>\n<p>TCP, HTTP&#8217;ye nazaran daha h\u0131zl\u0131 olaca\u011f\u0131ndan dolay\u0131 tercih edilebilir. \u00d6zellikle event eklendi\u011fi zaman subscribe olan consumer&#8217;larla zamansal a\u00e7\u0131dan 2|3 kat daha h\u0131zl\u0131 ileti\u015fim kurulabilmektedir. Bu fark y\u00fcksek performansl\u0131 ortamlarda daha da kendini g\u00f6sterecektir.<\/p>\n<h6>Event Store Kurulumu Nas\u0131l Yap\u0131l\u0131r?<\/h6>\n<p>Event Store&#8217;u ister PC&#8217;nize isterseniz de Docker ortam\u0131na kurabilirsiniz. Bizler bu i\u00e7eri\u011fimizde Docker&#8217;\u0131 tercih edece\u011fiz.<\/p>\n<p><strong>Docker<\/strong><br \/>\nEvent Store&#8217;u Docker ortam\u0131nda aya\u011fa kald\u0131rabilmek i\u00e7in a\u015fa\u011f\u0131daki komuttu \u00e7al\u0131\u015ft\u0131rabilirsiniz.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker run --name eventstore-node -it -p 2113:2113 -p 1113:1113 eventstore\/eventstore:release-5.0.9\r\n<\/pre>\n<p>Bu \u015fekilde Dockerize edilen Event Store sunucusuna ileride ba\u011flant\u0131 sa\u011flanmaya \u00e7al\u0131\u015f\u0131ld\u0131\u011f\u0131 zaman a\u015fa\u011f\u0131daki hata ka\u00e7\u0131n\u0131lmaz olacakt\u0131r.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"1707\" height=\"295\" class=\"aligncenter size-full wp-image-21583\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi.png 1707w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-300x52.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1024x177.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-768x133.png 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1536x265.png 1536w\" sizes=\"auto, (max-width: 1707px) 100vw, 1707px\" \/><\/a>Hatan\u0131n metinsel hali:<\/p>\n<blockquote><p><em style=\"color:red;\">EventStore.ClientAPI.Exceptions.RetriesLimitReachedException: Item Operation ReadStreamEventsForwardOperation<\/em><\/p><\/blockquote>\n<p>Bu hatan\u0131n kayna\u011f\u0131 ilgili sunucunun dahili bir SSL sertifikas\u0131 olmamas\u0131ndan kaynaklanmaktad\u0131r. \u0130lgili hatay\u0131 a\u015fabilmek i\u00e7in \u00f6ncelikle ger\u00e7ek sertifika kullan\u0131lmal\u0131d\u0131r. Bunun i\u00e7in Event Store&#8217;u kullanaca\u011f\u0131n\u0131z uygulamaya a\u015fa\u011f\u0131daki i\u00e7eri\u011fe sahip Dockerfile dosyas\u0131n\u0131 olu\u015fturunuz.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFROM eventstore\/eventstore:release-5.0.8\r\nRUN apt-get update -y \\\r\n  &amp;&amp; apt-get install -y openssl \\\r\n  &amp;&amp; openssl req -x509 -sha256 -nodes -days 3650 -subj &quot;\/CN=eventstore.org&quot; -newkey rsa:2048 -keyout eventstore.pem -out eventstore.csr \\\r\n  &amp;&amp; openssl pkcs12 -export -inkey eventstore.pem -in eventstore.csr -out eventstore.p12 -passout pass: \\\r\n  &amp;&amp; openssl pkcs12 -export -inkey eventstore.pem -in eventstore.csr -out eventstore.pfx -passout pass: \\\r\n  &amp;&amp; mkdir -p \/usr\/local\/share\/ca-certificates \\\r\n  &amp;&amp; cp eventstore.csr \/usr\/local\/share\/ca-certificates\/eventstore.crt \\\r\n  &amp;&amp; update-ca-certificates \\\r\n  &amp;&amp; apt-get autoremove \\\r\n  &amp;&amp; apt-get clean \\\r\n  &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/* \/tmp\/* \/var\/tmp\/*\r\n<\/pre>\n<p>Ard\u0131ndan powershell&#8217;den ilgili dizine odaklanarak a\u015fa\u011f\u0131dai image&#8217;i olu\u015fturunuz.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker build -t eventstore\/eventstore:with-cert-local --no-cache .\r\n<\/pre>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"1231\" height=\"227\" class=\"aligncenter size-full wp-image-21591\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1.png 1231w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1-300x55.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1-1024x189.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-1-768x142.png 768w\" sizes=\"auto, (max-width: 1231px) 100vw, 1231px\" \/><\/a>Son olarak a\u015fa\u011f\u0131daki gibi bir container&#8217;\u0131 aya\u011fa kald\u0131r\u0131n\u0131z.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\ndocker run --name EventStore -it -p 1113:1113 -p 1115:1115 -p 2113:2113 -e EVENTSTORE_CERTIFICATE_FILE=eventstore.p12 -e EVENTSTORE_EXT_SECURE_TCP_PORT=1115 eventstore\/eventstore:with-cert-local\r\n<\/pre>\n<p>Bu \u015fekilde aya\u011fa kald\u0131r\u0131lan container&#8217;da art\u0131k hata almayaca\u011f\u0131z. Yaz\u0131m\u0131z\u0131n devam\u0131nda ba\u011flant\u0131 kurmaya \u00e7al\u0131\u015faca\u011f\u0131m\u0131z container bu olacakt\u0131r. Ayr\u0131ca bu ayarlardan sonra art\u0131k TCP client&#8217;\u0131 olarak a\u015fa\u011f\u0131daki connection string&#8217;i kullanmam\u0131z gerekecektir.<br \/>\n<code style=\"color:purple;font-size:13px;\">\"ConnectTo=tcp:\/\/localhost:1115;DefaultUserCredentials=admin:changeit;UseSslConnection=true;<wbr>TargetHost=eventstore.org;ValidateServer=false\"<\/code><\/p>\n<h6>Event Store Admin UI Tan\u0131t\u0131m\u0131<\/h6>\n<p>Event Store container&#8217;\u0131 aya\u011fa kald\u0131rd\u0131ktan sonra <a href=\"http:\/\/localhost:2113\/\" rel=\"noopener\" target=\"_blank\">http:\/\/localhost:2113\/<\/a> adresi \u00fczerinden Admin UI&#8217;a eri\u015febilirsiniz.   Kullan\u0131c\u0131 ad\u0131 <code style=\"color:red;font-size:12px;\">admin<\/code>, \u015fifre <code style=\"color:red;font-size:12px;\">changeit<\/code>&#8216;tir.<\/p>\n<p>\u015eimdi s\u0131ras\u0131yla Admin UI&#8217;da ki sayfalar\u0131 incelemeye ba\u015flayal\u0131m.<\/p>\n<ul>\n<li><strong><em>Dashboard<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2-300x128.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"300\" height=\"128\" class=\"alignleft size-medium wp-image-21599\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2-300x128.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2-1024x436.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2-768x327.png 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2-1536x653.png 1536w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-2.png 1824w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Dashboard sayfas\u0131, olabildi\u011fince Event Store tool&#8217;unun istatiksel verilerini ve aktif ba\u011flant\u0131lar\u0131 \u00f6zet olarak sunan bir sayfad\u0131r.<br \/>&nbsp;<br \/>&nbsp;<br \/>&nbsp;\n<\/li>\n<li><strong><em>Stream Browser<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3-300x162.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"300\" height=\"162\" class=\"alignright size-medium wp-image-21602\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3-300x162.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3-1024x553.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3-768x415.png 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3-1536x829.png 1536w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-3.png 1726w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Event Store arac\u0131nda, event k\u00fcmelerine &#8216;stream&#8217; ad\u0131 verilmektedir. Dolay\u0131s\u0131yla ilgili tool&#8217;a depolanan event&#8217;lerin ak\u0131\u015f\u0131n\u0131 bu pencereden takip edebilmekteyiz.<br \/>&nbsp;<br \/>&nbsp;<br \/>&nbsp;\n<\/li>\n<li><strong><em>Event Stream<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4-300x57.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"300\" height=\"57\" class=\"alignleft size-medium wp-image-21603\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4-300x57.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4-1024x194.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4-768x146.png 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4-1536x291.png 1536w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-4.png 1834w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Bir stream&#8217;de ki eventlerin g\u00f6r\u00fcnt\u00fcs\u00fcn\u00fc veren sayfad\u0131r. Dikkat edilirse bir event&#8217;te :<br \/>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><strong>Event #<\/strong><\/td>\n<td>Event No<\/td>\n<\/tr>\n<tr>\n<td><strong>Name<\/strong><\/td>\n<td>Event ad\u0131<\/td>\n<\/tr>\n<tr>\n<td><strong>Type<\/strong><\/td>\n<td>Event t\u00fcr\u00fc\/tipi<\/td>\n<\/tr>\n<tr>\n<td><strong>Created Date<\/strong><\/td>\n<td>Event olu\u015fturulma tarihi<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>bilgileri mevcuttur. Bir ba\u015fka deyi\u015fle bir event bu bilgilerden meydana gelmektedir.\n<\/li>\n<\/ul>\n<h6>.NET Core \u0130le Event Store Kullan\u0131m\u0131<\/h6>\n<ul>\n<li><strong style=\"color:orange;\">Gereksinimler<\/strong><br \/>\n.NET Core ortam\u0131nda Event Store&#8217;u kullanabilmek i\u00e7in <a href=\"https:\/\/www.nuget.org\/packages\/EventStore.Client\/\" rel=\"noopener\" target=\"_blank\">EventStore.Client<\/a> k\u00fct\u00fcphanesinin y\u00fcklenmesi yeterlidir.\n<\/li>\n<li><strong style=\"color:orange;\">Event Store&#8217;a Ba\u011flanma<\/strong><br \/>\nEvent Store&#8217;a ba\u011flanabilmek i\u00e7in a\u015fa\u011f\u0131daki komutu kullanabilirsiniz :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            IEventStoreConnection connection = EventStoreConnection.Create(\r\n                connectionString: &quot;ConnectTo=tcp:\/\/localhost:1115;DefaultUserCredentials=admin:changeit;UseSslConnection=true;TargetHost=eventstore.org;ValidateServer=false&quot;,\r\n                connectionName: &quot;Console_Application&quot;,\r\n                builder: ConnectionSettings.Create().KeepReconnecting()\r\n                );\r\n\r\n            await connection.ConnectAsync();\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">Event Store Ba\u011flant\u0131 Olaylar\u0131<\/strong><br \/>\nEvent Store&#8217;a ba\u011flan\u0131rken a\u015fa\u011f\u0131daki ba\u011flant\u0131 olaylar\u0131ndan istifade edebilirsiniz :<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            connection.Connected += static (sender, clientConnectionEventArgs) =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Ba\u011flant\u0131 sa\u011flanm\u0131\u015ft\u0131r.&quot;);\r\n                Console.WriteLine($&quot;Connection Name  : {clientConnectionEventArgs.Connection.ConnectionName}&quot;);\r\n                Console.WriteLine($&quot;Address Family : {clientConnectionEventArgs.RemoteEndPoint.AddressFamily}&quot;);\r\n            };\r\n            connection.Disconnected += (sender, clientConnectionEventArgs) =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Ba\u011flant\u0131 kesilmi\u015ftir.&quot;);\r\n                Console.WriteLine($&quot;Connection Name  : {clientConnectionEventArgs.Connection.ConnectionName}&quot;);\r\n                Console.WriteLine($&quot;Address Family : {clientConnectionEventArgs.RemoteEndPoint.AddressFamily}&quot;);\r\n            };\r\n            connection.Reconnecting += (sender, clientReconnectingEventArgs) =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Ba\u011flant\u0131 yeniden deneniyor.&quot;);\r\n                Console.WriteLine($&quot;Connection Name  : {clientReconnectingEventArgs.Connection.ConnectionName}&quot;);\r\n            };\r\n            connection.ErrorOccurred += (sender, clientErrorEventArgs) =&gt;\r\n            {\r\n                Console.WriteLine(&quot;Hata olu\u015ftu!.&quot;);\r\n                Console.WriteLine($&quot;Connection Name  : {clientErrorEventArgs.Connection.ConnectionName}&quot;);\r\n                Console.WriteLine($&quot;Exception Message : {clientErrorEventArgs.Exception.Message}&quot;);\r\n            };\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">Event Ekleme<\/strong><br \/>\nEvent Store&#8217;a a\u015fa\u011f\u0131daki gibi event ekleyebilirsiniz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            EventData eventPayload = new(\r\n                eventId: Guid.NewGuid(),\r\n                type: &quot;EventAdded&quot;,\r\n                isJson: true,\r\n                data: Encoding.UTF8.GetBytes(&quot;Event eklenmi\u015ftir...&quot;),\r\n                metadata: Encoding.UTF8.GetBytes(&quot;Event metadata...&quot;)\r\n                );\r\n            var result = await connection.AppendToStreamAsync(&quot;Example-Event&quot;, ExpectedVersion.Any, eventPayload);\r\n<\/pre>\n<p>Dikkat edilirse e\u011fer Event Store&#8217;a at\u0131lacak olan event&#8217;ler &#8216;EventData&#8217; t\u00fcr\u00fcndendir.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-5-300x276.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"300\" height=\"276\" class=\"aligncenter size-medium wp-image-21622\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-5-300x276.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-5-768x706.png 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-5.png 948w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>\n<\/li>\n<li><strong style=\"color:orange;\">Event Okuma<\/strong><br \/>\nEvent Store&#8217;dan t\u00fcm event&#8217;leri okuyabilmek i\u00e7in ise a\u015fa\u011f\u0131daki gibi \u00e7al\u0131\u015f\u0131lmas\u0131 yeterli olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            StreamEventsSlice readEvents = await connection.ReadStreamEventsForwardAsync(&quot;Example-Event&quot;, 0, 100, true);\r\n            foreach (var @event in readEvents.Events)\r\n            {\r\n                Console.WriteLine($&quot;Data\\t\\t: {Encoding.UTF8.GetString(@event.Event.Data)}&quot;);\r\n                Console.WriteLine($&quot;Created \\t: {@event.Event.Created}&quot;);\r\n                Console.WriteLine($&quot;Created Epoch \\t: {@event.Event.CreatedEpoch}&quot;);\r\n                Console.WriteLine($&quot;EventId \\t: {@event.Event.EventId}&quot;);\r\n                Console.WriteLine($&quot;Event Number \\t: {@event.Event.EventNumber}&quot;);\r\n                Console.WriteLine($&quot;Event StreamId \\t: {@event.Event.EventStreamId}&quot;);\r\n                Console.WriteLine($&quot;Event Type \\t: {@event.Event.EventType}&quot;);\r\n                Console.WriteLine($&quot;Metadata \\t: {Encoding.UTF8.GetString(@event.Event.Metadata)}&quot;);\r\n                Console.WriteLine(&quot;|||||||||||||||||||||||||||&quot;);\r\n            }\r\n<\/pre>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-6-285x300.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"285\" height=\"300\" class=\"alignleft size-medium wp-image-21624\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-6-285x300.png 285w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-6.png 459w\" sizes=\"auto, (max-width: 285px) 100vw, 285px\" \/><\/a>Burada dikkat edilirse e\u011fer birden fazla event&#8217;i <code style=\"color:red;font-size:11px;\">ReadStreamEventsForwardAsync<\/code> fonskyionu arac\u0131l\u0131\u011f\u0131yla stream olarak okuyabilmekteyiz. \u0130lgili fonksiyon arac\u0131l\u0131\u011f\u0131yla opsiyonel aral\u0131kta event okuyabildi\u011fimiz i\u00e7in 0. event&#8217;ten ba\u015flayarak 100 adet event&#8217;i ileri d\u00f6n\u00fck okumas\u0131n\u0131 ve stream olarak d\u00f6nd\u00fcrmesini bildirmi\u015f bulunuyoruz.<\/p>\n<p>Benzer olarak <code style=\"color:red;font-size:11px;\">ReadStreamEventsBackwardAsync<\/code> fonksiyonu ilede geriye d\u00f6n\u00fck stream okumas\u0131 ger\u00e7ekle\u015ftirilebilmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nStreamEventsSlice readEvents = await connection.ReadStreamEventsBackwardAsync(&quot;Example-Event&quot;, 99, 100, true);\r\n<\/pre>\n<p>T\u00fcm bunlar\u0131n d\u0131\u015f\u0131nda <code style=\"color:red;font-size:11px;\">ReadAllEventsForwardAsync<\/code> ve <code style=\"color:red;font-size:11px;\">ReadAllEventsBackwardAsync<\/code> fonksiyonlar\u0131 sayesinde t\u00fcm stream&#8217;lerdeki olaylar\u0131 okuyabilmekteyiz. Bu fonksiyonlar stream olarak de\u011fil de normal bir \u015fekilde okuma ger\u00e7ekle\u015ftirir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            List&lt;ResolvedEvent&gt; allEvents = new();\r\n            Position nextSliceStart = Position.Start; \/\/ReadAllEventsBackwardAsync -&gt; Position.End\r\n            AllEventsSlice readEvents = null;\r\n            do\r\n            {\r\n                readEvents = await connection.ReadAllEventsForwardAsync(nextSliceStart, 200, true);\r\n                nextSliceStart = readEvents.NextPosition;\r\n                allEvents.AddRange(readEvents.Events);\r\n            } while (!readEvents.IsEndOfStream);\r\n\r\n            \/\/allEvents Foreach\r\n<\/pre>\n<p>Ayriyetten tekil olarak event number bazl\u0131 event okumas\u0131da ger\u00e7ekle\u015ftirebiliriz. Bunun i\u00e7inde a\u015fa\u011f\u0131daki gibi <code style=\"color:red;font-size:11px;\">ReadEventAsync<\/code> fonksiyonunun kullan\u0131lmas\u0131 yeterli olacakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            EventReadResult readResult = await connection.ReadEventAsync(&quot;Example-Event&quot;, 3, true);\r\n            Console.WriteLine($&quot;Data\\t\\t: {Encoding.UTF8.GetString(readResult.Event.Value.Event.Data)}&quot;);\r\n            Console.WriteLine($&quot;Created \\t: {readResult.Event.Value.Event.Created}&quot;);\r\n            Console.WriteLine($&quot;Created Epoch \\t: {readResult.Event.Value.Event.CreatedEpoch}&quot;);\r\n            Console.WriteLine($&quot;EventId \\t: {readResult.Event.Value.Event.EventId}&quot;);\r\n            Console.WriteLine($&quot;Event Number \\t: {readResult.Event.Value.Event.EventNumber}&quot;);\r\n            Console.WriteLine($&quot;Event StreamId \\t: {readResult.Event.Value.Event.EventStreamId}&quot;);\r\n            Console.WriteLine($&quot;Event Type \\t: {readResult.Event.Value.Event.EventType}&quot;);\r\n            Console.WriteLine($&quot;Metadata \\t: {Encoding.UTF8.GetString(readResult.Event.Value.Event.Metadata)}&quot;);\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">Event Store Transaction Kullan\u0131m\u0131<\/strong><br \/>\nEvent Store&#8217;da transaction ba\u015flat\u0131larak i\u015flemler ger\u00e7ekle\u015ftirilebilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    class Program\r\n    {\r\n        static async Task Main(string&#x5B;] args)\r\n        {\r\n            IEventStoreConnection connection = EventStoreConnection.Create(\r\n                connectionString: &quot;ConnectTo=tcp:\/\/localhost:1115;DefaultUserCredentials=admin:changeit;UseSslConnection=true;TargetHost=eventstore.org;ValidateServer=false&quot;,\r\n                connectionName: &quot;Console_Application&quot;,\r\n                builder: ConnectionSettings.Create().KeepReconnecting()\r\n                );\r\n            await connection.ConnectAsync();\r\n\r\n            using EventStoreTransaction transaction = await connection.StartTransactionAsync(&quot;Example-Event-3&quot;, ExpectedVersion.Any);\r\n            await transaction.WriteAsync(CreateSampleEvent(1));\r\n            await transaction.WriteAsync(CreateSampleEvent(2));\r\n            await connection.AppendToStreamAsync(&quot;Example-Event-3&quot;, ExpectedVersion.Any, CreateSampleEvent(3));\r\n            await transaction.WriteAsync(CreateSampleEvent(4));\r\n            await transaction.WriteAsync(CreateSampleEvent(5));\r\n            await transaction.CommitAsync();\r\n        }\r\n\r\n        static EventData CreateSampleEvent(int i)\r\n        {\r\n            return new EventData(\r\n              eventId: Guid.NewGuid(),\r\n                type: &quot;event-type&quot;,\r\n                isJson: true,\r\n                data: Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new { a = i })),\r\n                metadata: Encoding.UTF8.GetBytes(&quot;{}&quot;)\r\n            ); ;\r\n        }\r\n    }\r\n<\/pre>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-7.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-7.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"333\" height=\"907\" class=\"alignleft size-full wp-image-21638\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-7.png 333w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-7-110x300.png 110w\" sizes=\"auto, (max-width: 333px) 100vw, 333px\" \/><\/a>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer; <em><strong>12.<\/strong> ve <strong>18.<\/strong><\/em> sat\u0131r aral\u0131\u011f\u0131nda transaction i\u015flemleri ger\u00e7ekle\u015ftirilmi\u015ftir.<\/p>\n<p>Transaction, <em><strong>12.<\/strong><\/em> sat\u0131rdaki <code style=\"color:red;font-size:11px;\">StartTransactionAsync<\/code> fonksiyonuyla ba\u015flat\u0131lm\u0131\u015f ve ard\u0131ndan ilgili transaction \u00fczerinden <code style=\"color:red;font-size:11px;\">WriteAsync<\/code> metoduyla event&#8217;ler eklenmi\u015ftir. Transaction \u00fczerinden eklenen t\u00fcm eventler <em><strong>18.<\/strong><\/em> sat\u0131rda <code style=\"color:red;font-size:11px;\">CommitAsync<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla fiziksel olarak i\u015flenmi\u015ftir.<\/p>\n<p>Lakin burada <em><strong>15.<\/strong><\/em> sat\u0131ra dikkat ederseniz e\u011fer transaction&#8217;\u0131n d\u0131\u015f\u0131nda bir i\u015flem yap\u0131lmaktad\u0131r. Buradan anla\u015f\u0131lan transaction di\u011fer i\u015flemleri kilitlememekte ve rahatl\u0131kla farkl\u0131 transaction&#8217;lara izin vermektedir. Burada yap\u0131lan i\u015flem esas\u0131nda iki farkl\u0131 transaction ile ger\u00e7ekle\u015ftirilmektedir. Velhas\u0131l bu \u00f6rnek kodu \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda event&#8217;lerin kay\u0131t s\u0131ras\u0131 yandaki g\u00f6rseldeki gibi olacakt\u0131r. (S\u0131ra : 3 &#8211; 1 &#8211; 2 &#8211; 4 &#8211; 5)<\/p>\n<p><em>Neden event&#8217;lerin s\u0131ras\u0131 bu \u015fekilde oldu?<\/em> diye sorarsan\u0131z e\u011fer cevab\u0131m\u0131z, <code style=\"color:red;font-size:11px;\">AppendToStreamAsync<\/code> fonksiyonunun transaction&#8217;\u0131 direkt commit etmesidir. Zaten transaction y\u00f6netimindeki nihai gayemiz commit i\u015fleminin irademizle ger\u00e7ekle\u015ftirilip daha tutarl\u0131 bir \u00e7al\u0131\u015fma yapmak de\u011fil midir? \ud83d\ude42<\/p>\n<p>Ayr\u0131ca bir transaction&#8217;\u0131 <code style=\"color:red;font-size:11px;\">transaction.Rollback()<\/code> metoduyla rollback edebilir ve t\u00fcm i\u015flemleri geri alabilirsiniz.\n<\/li>\n<li><strong style=\"color:orange;\">Stream Silme<\/strong><br \/>\nOlu\u015fturulan bir stream&#8217;i silmek isterseniz <code style=\"color:red;font-size:11px;\">DeleteStreamAsync<\/code> metodunu kullanabilirsiniz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nDeleteResult deleteResult = await connection.DeleteStreamAsync(&quot;Example-Event-3&quot;, ExpectedVersion.Any);\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:orange;\">Subscriptions\/Message Broker<\/strong><br \/>\n\u015eahsi kanaatimce Event Store&#8217;un en g\u00fczel \u00f6zelliklerinden birisi dahili message broker yap\u0131lanmas\u0131 bar\u0131nd\u0131r\u0131yor olmas\u0131d\u0131r. Bir stream&#8217;e <code style=\"color:red;font-size:11px;\">AppendToStreamAsync<\/code> ile eklenen herhangi bir event&#8217;ten an\u0131nda haberdar olabilmek i\u00e7in ilgili stream&#8217;e subscribe olabilmekte ve ger\u00e7ekle\u015fen i\u015flemlerle ilgili bildirimler al\u0131nabilmektedir. Esas\u0131nda Messaging ismini verdi\u011fimiz bu olay sayesinde eklenen event&#8217;e dair bilgiler edinmekte ve bu bilgiler e\u015fli\u011finde genellikle reading veritaban\u0131na gerekli g\u00fcncellemeler yans\u0131t\u0131lmaktad\u0131r.<\/p>\n<p>Bu \u00f6zelli\u011fin birbirinden g\u00fczel \u00fc\u00e7 niteli\u011fi mevcuttur. Bunlardan ilki, bildirimleri mevcut event&#8217;lerin d\u0131\u015f\u0131nda gelecek olanlar i\u00e7inde sa\u011flayabiliyor olmas\u0131d\u0131r. Yani demek istenilen o ki, 100 event varsa e\u011fer bizler 101.&#8217;den itibaren bildirim almay\u0131 tercih edebilmekteyiz. \u0130\u015fte buna <em style=\"color:purple;\">Volatile Subscriptions(De\u011fi\u015fken Abonelikler)<\/em> denmektedir.<\/p>\n<p>\u0130kincisi, belirli bir limitin \u00fcst\u00fcndeki event&#8217;lerin de bildirimini talep edebiliriz. Buna da \u00f6rnek vermek gerekirse, 100 event&#8217;lik bir durumda ba\u015flang\u0131\u00e7 noktas\u0131n\u0131 50 olarak belirleyebilir ve 51.&#8217;den sonraki t\u00fcm event&#8217;lerin bildirimini alabilirsiniz. Buna da <em style=\"color:purple;\">Catch-up Subscriptions(Yakalama Abonelikleri)<\/em> denmektedir. Bu her iki abonelik t\u00fcr\u00fcde ba\u011flant\u0131 koptu\u011fu taktirde son bulmaktad\u0131r. <\/p>\n<p>Sonuncu olarak, EventStoreDB&#8217;nin 3.2.0 versiyonundan sonra gelen ve ba\u011flant\u0131 koptu\u011fu durumlarda di\u011fer t\u00fcrlerin aksine mevcut subscribe&#8217;\u0131 koparmayan <em style=\"color:purple;\">Persistent Subscriptions(Kal\u0131c\u0131 Abonelikler)<\/em> mevcuttur. Bu abonelik t\u00fcr\u00fcnde, abonelik durumu sunucu taraf\u0131nda kaydedilmekte ve ayn\u0131 stream \u00fczerindeki birden fazla customer&#8217;a en az bir kez message iletiminin garantisini vermektedir. <\/p>\n<p>\u015eimdi gelin bu \u00fc\u00e7 niteli\u011fi pratikte inceleyelim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            EventStoreSubscription subscription = await connection.SubscribeToStreamAsync(\r\n                    stream: &quot;Example-Event-7&quot;,\r\n                    resolveLinkTos: true,\r\n                    eventAppeared: async (eventStoreSubscription, resolvedEvent)\r\n                        =&gt; Console.WriteLine($&quot;Event eklenmi\u015ftir.{Encoding.UTF8.GetString(resolvedEvent.Event.Data)}&quot;),\r\n                    subscriptionDropped: (eventStoreSubscription, subscriptionDropReason, exception)\r\n                        =&gt; Console.WriteLine($&quot;Ba\u011flant\u0131 kopmu\u015ftur. {subscriptionDropReason}&quot;)\r\n                    );\r\n\r\n            int i = 0;\r\n            while (i++ &lt; 10)\r\n            {\r\n                EventData eventPayload = new(\r\n                    eventId: Guid.NewGuid(),\r\n                    type: &quot;EventAdded&quot; + i,\r\n                    isJson: true,\r\n                    data: Encoding.UTF8.GetBytes(&quot;Event eklenmi\u015ftir...&quot; + i),\r\n                    metadata: Encoding.UTF8.GetBytes(&quot;Event metadata...&quot; + i)\r\n                 );\r\n                var result = await connection.AppendToStreamAsync(&quot;Example-Event-7&quot;, ExpectedVersion.Any, eventPayload);\r\n            }\r\n<\/pre>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-8.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-8.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"327\" height=\"168\" class=\"alignleft size-full wp-image-21665\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-8.png 327w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-8-300x154.png 300w\" sizes=\"auto, (max-width: 327px) 100vw, 327px\" \/><\/a>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer connection nesnesinin <code style=\"color:red;font-size:11px;\">SubscribeToStreamAsync<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla &#8216;stream&#8217; parametresine verilen de\u011ferdeki stream&#8217;e subscribe olunmaktad\u0131r. S\u00fcre\u00e7te herhangi bir event eklendi\u011fi vakit &#8216;eventAppeared&#8217; delegasyonuna ba\u011flanan fonksiyon tetiklenmekte ve gerekli aksiyon al\u0131nabilmektedir.<\/p>\n<p>A\u015fa\u011f\u0131daki gibi <code style=\"color:red;font-size:11px;\">SubscribeToStreamFrom<\/code> fonksiyonu ile de konfig\u00fcrasyona detayl\u0131 m\u00fcdahale ederek, subscribe i\u015flemini ger\u00e7ekle\u015ftirebilirsiniz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            CatchUpSubscriptionSettings settings = new(\r\n                maxLiveQueueSize: 10000,\r\n                readBatchSize: 5,\r\n                verboseLogging: false,\r\n                resolveLinkTos: true,\r\n                subscriptionName: &quot;mySubscription&quot;\r\n                );\r\n            connection.SubscribeToStreamFrom(\r\n                stream: &quot;Example-Event-8&quot;,\r\n                settings: settings,\r\n                lastCheckpoint: StreamPosition.Start,\r\n                eventAppeared: async (eventStoreSubscription, resolvedEvent)\r\n                    =&gt; Console.WriteLine($&quot;Event eklenmi\u015ftir.{Encoding.UTF8.GetString(resolvedEvent.Event.Data)}&quot;),\r\n                liveProcessingStarted: eventStoreCatchUpSubscription\r\n                   =&gt; Console.WriteLine(&quot;\u0130\u015flenmeye devam ediyor...&quot;),\r\n                subscriptionDropped: (eventStoreSubscription, subscriptionDropReason, exception)\r\n                    =&gt; Console.WriteLine($&quot;Ba\u011flant\u0131 kopmu\u015ftur. {subscriptionDropReason}&quot;)\r\n                );\r\n<\/pre>\n<p><em style=\"font-size:11px;\">Peki, Asp.NET Core&#8217;da yahut farkl\u0131 bir client&#8217;ta bu stream&#8217;lere nas\u0131l subscribe olaca\u011f\u0131z?<\/em> sorunuzu duyar gibiyim&#8230;<\/p>\n<p>Event eklendi\u011finde abone olunan stream&#8217;i dinleyebilmek i\u00e7in bir Background Service olu\u015fturabilir yahut console, api vs. gibi harici bir servis taraf\u0131ndan ilgili stream&#8217;e subscribe yapabilirsiniz. A\u015fa\u011f\u0131daki \u00f6rnek kod blo\u011funda Background Service ile bir incele yap\u0131lm\u0131\u015ft\u0131r. Yaz\u0131n\u0131n devam\u0131nda ise console \u00fczerinden harici bir servis \u00fczerinden de teoride \u00f6rneklendirme ger\u00e7ekle\u015ftirilecektir. Asp.NET Core mimarisinde background service olu\u015fturabilmek i\u00e7in <code>Microsoft.Extensions.Hosting<\/code> namespace&#8217;in de ki <code>BackgroundService<\/code> s\u0131n\u0131f\u0131n\u0131 a\u015fa\u011f\u0131daki gibi kullanmam\u0131z gerekmektedir. Ayr\u0131ca ilgili projeye malum k\u00fct\u00fcphanenin(EventStore.Client) y\u00fcklenmesi gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class EventStoreBackgroundService : BackgroundService\r\n    {\r\n        readonly IEventStoreConnection _connection;\r\n        public EventStoreBackgroundService(\r\n            IEventStoreConnection connection)\r\n        {\r\n            _connection = connection;\r\n        }\r\n        protected override async Task ExecuteAsync(CancellationToken stoppingToken)\r\n        {\r\n            await _connection.SubscribeToStreamAsync(\r\n                 stream: &quot;Example-Event-10&quot;,\r\n                 resolveLinkTos: true,\r\n                 eventAppeared: async (eventStoreSubscription, resolvedEvent)\r\n                     =&gt; Console.WriteLine($&quot;Event eklenmi\u015ftir.{Encoding.UTF8.GetString(resolvedEvent.Event.Data)}&quot;),\r\n                 subscriptionDropped: (eventStoreSubscription, subscriptionDropReason, exception)\r\n                     =&gt; Console.WriteLine($&quot;Ba\u011flant\u0131 kopmu\u015ftur. {subscriptionDropReason}&quot;)\r\n                 );\r\n        }\r\n    }\r\n<\/pre>\n<p>Ard\u0131ndan &#8216;Startup.cs&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki konfig\u00fcrasyonlar\u0131n yap\u0131lmas\u0131 gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            IEventStoreConnection connection = EventStoreConnection.Create(\r\n               connectionString: &quot;ConnectTo=tcp:\/\/localhost:1115;DefaultUserCredentials=admin:changeit;UseSslConnection=true;TargetHost=eventstore.org;ValidateServer=false&quot;,\r\n               connectionName: &quot;Console_Application&quot;,\r\n               builder: ConnectionSettings.Create().KeepReconnecting()\r\n               );\r\n\r\n            connection.ConnectAsync().GetAwaiter().GetResult();\r\n            services.AddSingleton(connection);\r\n            services.AddHostedService&lt;EventStoreBackgroundService&gt;();\r\n            services.AddControllers();\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<p>Asp.NET Core i\u00e7in yap\u0131lmas\u0131 gereken konfig\u00fcrasyon i\u015fte bu kadar&#8230;<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-9.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-9.png\" alt=\".NET Core Ortam\u0131nda &#039;Event Store&#039; \u0130le Event Sourcing Yap\u0131lanmas\u0131\" width=\"438\" height=\"325\" class=\"aligncenter size-full wp-image-21673\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-9.png 438w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/NET-Core-Ortaminda-Event-Store-Ile-Event-Sourcing-Yapilanmasi-9-300x223.png 300w\" sizes=\"auto, (max-width: 438px) 100vw, 438px\" \/><\/a><br \/>\nConsole \u00fczerinden \u00f6rneklendirmeye gelirsek e\u011fer yine ayn\u0131 isimde stream&#8217;i dinleyen bir ba\u011flant\u0131 olu\u015fturulmas\u0131 ve ona yukar\u0131da incelenen fonksiyonlardan biriyle subscribe olunmas\u0131 yeterli olacakt\u0131r.\n<\/li>\n<\/ul>\n<p>Nihai olarak,<br \/>\nEvent Sourcing pattern&#8217;\u0131 uygulayabilmek i\u00e7in veriler \u00fczerindeki de\u011fi\u015fiklikleri ifade edecek olan event&#8217;leri depolayabilmek i\u00e7in kullanaca\u011f\u0131m\u0131z Event Store tool&#8217;unu detayl\u0131ca incelemi\u015f bulunmaktay\u0131z. Haliyle bu bilgiler temelinde sonraki makalemizde Event Store&#8217;u kullanarak Event Sourcing&#8217;e dair pratiksel bir \u00f6rnek ger\u00e7ekle\u015ftiriyor olaca\u011f\u0131z. O halde sonraki makalemizde g\u00f6r\u00fc\u015fmek \u00fczere diyelim&#8230;<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek kod dosyalar\u0131n\u0131 indirmek i\u00e7in <a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/EventSourcingExample.zip\" rel=\"noopener\" target=\"_blank\">buraya<\/a> t\u0131klay\u0131n\u0131z.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bir \u00f6nceki Basit Bir Event Sourcing Uygulamas\u0131 Geli\u015ftirelim ba\u015fl\u0131kl\u0131 makalemizde Event Sourcing pattern&#8217;\u0131n\u0131n nas\u0131l ger\u00e7ekle\u015ftirilebildi\u011fine pratiksel olarak bir \u00f6rnek vermeye \u00e7al\u0131\u015fm\u0131\u015ft\u0131k. \u0130lgili makalede ele al\u0131nan \u00f6rnekten de g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere uygulamada ger\u00e7ekle\u015ftirilen &#8216;event&#8217;lerin in-memory&#8217;de&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":21677,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,153,3573],"tags":[4241,4246,4245,4217,4225,4230,4243,4238,4249,4248,4237,4236,4235,4234,4231,4232,4233,4239,4250,4251,4242,4244,4247],"class_list":["post-21574","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-design-pattern","category-microservices","tag-appendtostreamasync","tag-catch-up-subscriptions","tag-degisken-abonelikler","tag-event-sourcing","tag-event-store","tag-event-store-kurulumu","tag-event-store-subscriptions","tag-event-store-transaction-kullanimi","tag-kalici-abonelikler","tag-persistent-subscriptions","tag-readalleventsbackwardasync","tag-readalleventsforwardasync","tag-readstreameventsbackwardasync","tag-readstreameventsforwardasync","tag-readstreameventsforwardoperation","tag-retrieslimitreachedexception","tag-retrieslimitreachedexception-error-solution","tag-starttransactionasync","tag-subscribetostreamasync","tag-subscribetostreamfrom","tag-subscriptions","tag-volatile-subscriptions","tag-yakalama-abonelikleri"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=21574"}],"version-history":[{"count":93,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21574\/revisions"}],"predecessor-version":[{"id":21680,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21574\/revisions\/21680"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/21677"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=21574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=21574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=21574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}