﻿
{"id":21681,"date":"2021-05-20T03:24:52","date_gmt":"2021-05-20T03:24:52","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=21681"},"modified":"2021-05-20T03:25:50","modified_gmt":"2021-05-20T03:25:50","slug":"asp-net-core-event-store-ile-event-sourcing-uygulamasiorneklendirme","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-event-store-ile-event-sourcing-uygulamasiorneklendirme\/","title":{"rendered":"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>\u00d6nceki, <a href=\"https:\/\/www.gencayyildiz.com\/blog\/net-core-ortaminda-event-store-ile-event-sourcing-yapilanmasi\/\" rel=\"noopener\" target=\"_blank\">.NET Core Ortam\u0131nda \u2018Event Store\u2019 \u0130le Event Sourcing Yap\u0131lanmas\u0131<\/a> ba\u015fl\u0131kl\u0131 makalemde Event Sourcing yap\u0131lanmas\u0131 i\u00e7in Event Store ile yap\u0131lmas\u0131 gereken temel ayarlardan ve ba\u011flant\u0131 konfig\u00fcrasyonlar\u0131ndan bahsetmi\u015ftik. Bu i\u00e7eri\u011fimizde ise bir Asp.NET Core uygulamas\u0131nda belirledi\u011fimiz bir senaryoya istinaden Event Store tool&#8217;unun e\u015fli\u011finde Event Sourcing \u00f6rneklendirmesi ger\u00e7ekle\u015ftirece\u011fiz. Haliyle hi\u00e7 vakit kaybetmeksizin direkt olarak i\u00e7eri\u011fimizin temeli olan senaryoyu ele alarak konuya giri\u015f yapal\u0131m.<\/p>\n<h4>Senaryo<\/h4>\n<p>\u00d6rneklendirmede ele alaca\u011f\u0131m\u0131z senaryo bir sistemdeki kullan\u0131c\u0131(Users) davran\u0131\u015flar\u0131 \u00fczerine olacakt\u0131r. Bir kullan\u0131c\u0131 datas\u0131 \u00fczerinde varsay\u0131m olarak olu\u015fabilecek t\u00fcm event&#8217;ler a\u015fa\u011f\u0131daki tabloda listelenmi\u015ftir.<\/p>\n<table>\n<thead>\n<tr>\n<th>A\u00e7\u0131klama<\/th>\n<th>Event<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Kullan\u0131c\u0131 eklendi\u011finde<\/td>\n<td><em style=\"color:red;\">UserCreated<\/em><\/td>\n<\/tr>\n<tr>\n<td>Kullan\u0131c\u0131 ad\u0131 de\u011fi\u015ftirildi\u011finde<\/td>\n<td><em style=\"color:red;\">UserNameChanged<\/em><\/td>\n<\/tr>\n<tr>\n<td>Kullan\u0131c\u0131 email&#8217;i onayland\u0131\u011f\u0131nda<\/td>\n<td><em style=\"color:red;\">UserEmailApproved<\/em><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>Ba\u015flarken<\/h4>\n<p>Yap\u0131sal olarak Event Sourcing i\u00e7in bir data \u00fczerindeki t\u00fcm etkinliklerin kay\u0131t alt\u0131nda tutuldu\u011fu bir pattern oldu\u011funu \u00f6nceki makalelerimizde uzun uzad\u0131ya konu\u015fmu\u015ftuk. Haliyle \u015fimdi bu pattern&#8217;\u0131 uygularken yapt\u0131\u011f\u0131m\u0131z girizgahtan da belli oldu\u011fu \u00fczere data \u00fczerindeki etkinliklerin kayd\u0131n\u0131 Event Store tool&#8217;un da tutacak ve b\u00f6ylece &#8216;Write Data Store&#8217; olarak ilgili veritaban\u0131n\u0131 kullanaca\u011f\u0131z. &#8216;Read Data Store&#8217; olarak kullan\u0131lacak olan veritaban\u0131ndaki g\u00fcncellemeyi ise Messaging ile ger\u00e7ekle\u015ftirece\u011fiz ve bu i\u015flemi de muhtemelen bir sonraki makalemizde ele al\u0131yor olaca\u011f\u0131z.<br \/>\n<div id=\"attachment_21690\" style=\"width: 806px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-21690\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"796\" height=\"319\" class=\"size-full wp-image-21690\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme.png 796w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-300x120.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-768x308.png 768w\" sizes=\"auto, (max-width: 796px) 100vw, 796px\" \/><\/a><p id=\"caption-attachment-21690\" class=\"wp-caption-text\"><span style=\"font-size:9px;\">G\u00f6rsel Kayna\u011f\u0131 : https:\/\/subscription.packtpub.com\/book\/application_development\/9781786469342\/7\/07lvl1sec43\/event-sourcing-and-cqrs<\/span><br \/>\nEsas\u0131nda g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere Event Sourcing, <a href=\"https:\/\/www.gencayyildiz.com\/blog\/cqrs-pattern-nedir-mediatr-kutuphanesi-ile-nasil-uygulanir\/\" rel=\"noopener\" target=\"_blank\">CQRS pattern<\/a> ile birlikte tam bir uyumluluk sergilemekte olan bir yap\u0131land\u0131r. &#8216;Write Data Store&#8217; olarak herhangi bir veritaban\u0131 yahut sa\u011flay\u0131c\u0131 kullan\u0131labilir. Biz burada olduk\u00e7a etkili olan Event Store tool&#8217;unu tercih ediyoruz. Amma velakin bir event geldi\u011fi taktirde bu yenili\u011fi anl\u0131k olarak &#8216;Read Data Store&#8217; veritaban\u0131na yans\u0131t\u0131lmas\u0131 elzemdir. Aksi taktirde b\u00fcy\u00fck bir veri tutars\u0131zl\u0131\u011f\u0131 s\u00f6z konusu olabilir. Bu konuya da yukar\u0131da da bahsedildi\u011fi \u00fczere sonraki makalemizde de\u011finmi\u015f olacak olsakta, bu makalemizin ileriki sat\u0131rlar\u0131nda ufaktan temas etmi\u015f olaca\u011f\u0131z&#8230;<\/p><\/div><br \/>\nVelhas\u0131l, \u00f6rneklendirmede e\u015flik edebilmeniz i\u00e7in hali haz\u0131rda olu\u015fturulmu\u015f bir Asp.NET Core &#8211; API uygulamas\u0131 a\u00e7\u0131n\u0131z ve i\u00e7erisine <a href=\"https:\/\/www.nuget.org\/packages\/EventStore.Client\/\" rel=\"noopener\" target=\"_blank\">EventStore.Client<\/a> k\u00fct\u00fcphanesini y\u00fckleyiniz. Ard\u0131ndan geli\u015ftirilmeye haz\u0131r bir adet &#8216;UsersController&#8217; isminde controller olu\u015fturunuz. Evet, art\u0131k bu kadar\u0131 kafidir. Yava\u015ftan event sourcing pattern&#8217;\u0131n\u0131 geli\u015ftirmeye ba\u015flayabiliriz.<\/p>\n<h4>Uygulama Geli\u015ftirme<\/h4>\n<p>Bu makalede belli ba\u015fl\u0131 bir event sourcing stratejisi g\u00f6sterilecektir. Tabi ki de bu strateji \u00f6zelle\u015ftirilebilir yahut daha farkl\u0131 stratejilerde bir tasar\u0131m ortaya koyulabilir. Ayr\u0131ca ad\u0131m ad\u0131m geli\u015ftirme s\u00fcre\u00e7lerinde iste\u011finiz ya da ihtiyac\u0131n\u0131z do\u011frultusunda \u00f6ncelik s\u0131ralamas\u0131n\u0131 de\u011fi\u015ftirebilirsiniz. Misal, bizler a\u015fa\u011f\u0131da \u00f6ncelikle event&#8217;lerin geli\u015ftirilmesinden ba\u015flayaca\u011f\u0131z. Sizler isterseniz \u00f6ncelikle exception s\u0131n\u0131flar\u0131n\u0131 geli\u015ftirebilir yahut &#8216;Aggregate&#8217;<span style=\"font-size:10px;\">(yaz\u0131m\u0131z\u0131n devam\u0131nda ne i\u015fe yarad\u0131\u011f\u0131 anlat\u0131lacakt\u0131r)<\/span> s\u0131n\u0131f\u0131n\u0131 ele alabilirsiniz. Yeter ki ola\u011fan olsun \ud83d\ude42<\/p>\n<ul>\n<li><strong>Ad\u0131m 1<\/strong> <em style=\"color:green;\">Entity&#8217;nin Olu\u015fturulmas\u0131<\/em><br \/>\n\u0130lk olarak hangi model \u00fczerinde event sourcing operasyonu ger\u00e7ekle\u015ftirdi\u011fimizi bilmek i\u00e7in \u00f6ncelikle entity model&#8217;imizi olu\u015ftural\u0131m.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class User\r\n    {\r\n        public int Id { get; set; }\r\n        public string Name { get; set; }\r\n        public string UserName { get; set; }\r\n        public string Email { get; set; }\r\n        public bool EmailApprove { get; set; }\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 2<\/strong> <em style=\"color:green;\">Event&#8217;lerin Olu\u015fturulmas\u0131<\/em><br \/>\nBir event sourcing tasar\u0131m\u0131nda en \u00f6nemli akt\u00f6rler event&#8217;lerdir. Dolay\u0131s\u0131yla bu event&#8217;leri tarif eden, onlara kar\u015f\u0131l\u0131k gelen s\u0131n\u0131flar\u0131n \u00fcretilmesi gerekmektedir. Tabi ki de bu s\u0131n\u0131flar\u0131n sistemde bir event oldu\u011funa dair ay\u0131rt edici bir \u00f6zellikle i\u015faretlenmesi i\u00e7in \u00f6ncelikle bir &#8216;IEvent&#8217; ad\u0131nda interface olu\u015fturabiliriz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface IEvent\r\n    {\r\n    }\r\n<\/pre>\n<p>Bu interface ile uygulamada ki t\u00fcm event&#8217;lerimizi i\u015faretleyece\u011fiz.<\/p>\n<p><u>UserCreated<\/u>, kullan\u0131c\u0131 eklendi\u011fini\/olu\u015fturuldu\u011funu tarif eden event&#8217;tir. \u0130\u00e7eriksel olarak bir kullan\u0131c\u0131y\u0131 olu\u015fturmak i\u00e7in gerekli datalar\u0131 tutacak property&#8217;ler tan\u0131mlanm\u0131\u015ft\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserCreated : IEvent\r\n    {\r\n        public int UserId { get; set; }\r\n        public string Name { get; set; }\r\n        public string UserName { get; set; }\r\n        public string Email { get; set; }\r\n        public bool EmailApprove { get; set; }\r\n    }\r\n<\/pre>\n<p><u>UserNameChanged<\/u>, kullan\u0131c\u0131n\u0131n ad\u0131n\u0131n g\u00fcncellendi\u011fini tarif eden event&#8217;tir. \u0130\u00e7erisinde hangi kullan\u0131c\u0131ya dair(UserId) hangi yeni isim bilgilerini(NewName) tutacak olan property&#8217;ler tan\u0131mlanm\u0131\u015ft\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserNameChanged : IEvent\r\n    {\r\n        public int UserId { get; set; }\r\n        public string NewName { get; set; }\r\n    }\r\n<\/pre>\n<p><u>UserEmailApproved<\/u>, kullan\u0131c\u0131 email&#8217;inin do\u011fruland\u0131\u011f\u0131n\u0131 tarif eden event&#8217;tir. Bu i\u015flemin hangi kullan\u0131c\u0131 i\u00e7in yap\u0131ld\u0131\u011f\u0131n\u0131 bilmemiz yeterli olaca\u011f\u0131ndan dolay\u0131 sadece UserId bilgisi tutulmaktad\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserEmailApproved : IEvent\r\n    {\r\n        public int UserId { get; set; }\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 3<\/strong> <em style=\"color:green;\">Exception S\u0131n\u0131flar\u0131n\u0131n Olu\u015fturulmas\u0131<\/em><br \/>\nUygulamadaki event sourcing s\u00fcrecinde olu\u015fabilecek istisnai durumlar\u0131 tarif edebilmek ve daha dinamik y\u00f6netebilmek i\u00e7in gerekli exception s\u0131n\u0131flar\u0131 olu\u015fturulmal\u0131d\u0131r. Misal olarak, olu\u015fan herhangi bir event&#8217;i gerekli k\u00fcmeye\/aggregate&#8217;e\/stream&#8217;e atayabilmek i\u00e7in \u00f6ncelikle ilgili stream&#8217;in var olmas\u0131 gerekmektedir. Aksi taktirde a\u015fa\u011f\u0131daki <code style=\"color:red;font-size:12px;\">StreamNotFoundException<\/code> isimli exception s\u0131n\u0131f\u0131 f\u0131rlat\u0131larak, sistem uyar\u0131labilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class StreamNotFoundException : Exception\r\n    {\r\n        public StreamNotFoundException() : base(&quot;Stream not found&quot;)\r\n        { }\r\n        public StreamNotFoundException(string message) : base(message)\r\n        { }\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 4<\/strong> <em style=\"color:green;\">Aggregate Abstract Class&#8217;\u0131n\u0131n Olu\u015fturulmas\u0131<\/em><br \/>\nBir kullan\u0131c\u0131 verisine kar\u015f\u0131l\u0131k olu\u015fabilecek t\u00fcm event&#8217;lerin toplam\u0131 olan &#8216;Aggregate&#8217;i temsil edecek olan abstract class&#8217;\u0131n a\u015fa\u011f\u0131daki gibi tasarlanmas\u0131 olduk\u00e7a idealdir. Gerekli a\u00e7\u0131klamalar kodun i\u00e7erisinde yap\u0131lm\u0131\u015ft\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public abstract class Aggregate\r\n    {\r\n        \/\/Olu\u015fan t\u00fcm event'leri tutacak koleksiyon.\r\n        protected readonly List&lt;IEvent&gt; events = new();\r\n        public List&lt;IEvent&gt; GetEvents =&gt; events;\r\n        \/\/Event'lerin tutulaca\u011f\u0131 Aggregate\/Stream ad\u0131.\r\n        public string StreamName { get; private set; }\r\n        public void SetStreamName(string streamName)\r\n            =&gt; StreamName = streamName;\r\n        \/\/Stream ad\u0131n\u0131n atan\u0131p atanmad\u0131\u011f\u0131n\u0131 kontrol eden fonksiyon.\r\n        protected bool CheckStreamName()\r\n            =&gt; string.IsNullOrEmpty(StreamName) || string.IsNullOrWhiteSpace(StreamName);\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 5<\/strong> <em style=\"color:green;\">&#8216;UserAggregate&#8217; S\u0131n\u0131f\u0131n\u0131n Tasarlanmas\u0131<\/em><br \/>\n&#8216;Aggregate&#8217; abstract class&#8217;\u0131n\u0131 tasarlad\u0131ktan sonra art\u0131k s\u0131rada concrete aggregate s\u0131n\u0131flar\u0131n\u0131n tasarlanmas\u0131 vard\u0131r. Bizler bu makalemizde sadece kullan\u0131c\u0131 \u00fczerinde bir event sourcing \u00e7al\u0131\u015fmas\u0131 yapt\u0131\u011f\u0131m\u0131z i\u00e7in a\u015fa\u011f\u0131daki gibi <code style=\"color:red;font-size:12px;\">UserAggregate<\/code> isimli bir s\u0131n\u0131f\u0131n tasarlanmas\u0131 yeterli olacakt\u0131r. Sizler ise projenizde bulunan farkl\u0131 aggregate&#8217;lere g\u00f6re concrete&#8217;leri olu\u015fturmal\u0131 ve ihtiyaca binaen gerekli \u00e7al\u0131\u015fmalar\u0131 sergilemelisiniz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserAggregate : Aggregate\r\n    {\r\n        \/\/Kullan\u0131c\u0131 olu\u015fturuldu\u011funda\r\n        public void Created(User model)\r\n        {\r\n            if (CheckStreamName())\r\n                throw new StreamNotFoundException();\r\n\r\n            UserCreated userCreated = new()\r\n            {\r\n                UserId = model.Id,\r\n                Email = model.Email,\r\n                EmailApprove = model.EmailApprove,\r\n                Name = model.Name,\r\n                UserName = model.UserName\r\n            };\r\n            events.Add(userCreated);\r\n        }\r\n        \/\/Kullan\u0131c\u0131 ad\u0131 de\u011fi\u015ftirildi\u011finde\r\n        public void NameChanged(string newName, int userId)\r\n        {\r\n            if (CheckStreamName())\r\n                throw new StreamNotFoundException();\r\n\r\n            UserNameChanged userNameChanged = new()\r\n            {\r\n                NewName = newName,\r\n                UserId = userId\r\n            };\r\n            events.Add(userNameChanged);\r\n        }\r\n        \/\/Kullan\u0131c\u0131 email onayland\u0131\u011f\u0131nda\r\n        public void EmailApproved(int userId)\r\n        {\r\n            if (CheckStreamName())\r\n                throw new StreamNotFoundException();\r\n\r\n            UserEmailApproved userEmailApproved = new()\r\n            {\r\n                UserId = userId\r\n            };\r\n            events.Add(userEmailApproved);\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki concrete aggregate s\u0131n\u0131f\u0131n\u0131 incelerseniz e\u011fer bir kullan\u0131c\u0131 verisi \u00fczerinde olu\u015fabilecek t\u00fcm olaylar\u0131n fonksiyonlar\u0131n\u0131 bar\u0131nd\u0131rmakta ve bu fonksiyonlar i\u00e7erisinde ilgili olaya dair instance \u00fcretilerek base class&#8217;ta ki &#8216;events&#8217; isimli koleksiyona at\u0131lmaktad\u0131r. Art\u0131k bu concrete aggregate s\u0131n\u0131f\u0131 sayesinde \u00fcretilmi\u015f olan event&#8217;leri Event Store&#8217;a g\u00f6nderecek ve ihtiya\u00e7 do\u011frultusunda tekrar elde etmemizi sa\u011flayacak repository s\u0131n\u0131f\u0131n\u0131n tasarlanmas\u0131 gerekmektedir.\n<\/li>\n<li><strong>Ad\u0131m 6<\/strong> <em style=\"color:green;\">AggregateRepository S\u0131n\u0131f\u0131n\u0131n Tasarlanmas\u0131<\/em><br \/>\nA\u015fa\u011f\u0131da olu\u015fturulmu\u015f olan aggregate repository s\u0131n\u0131f\u0131 ile yukar\u0131daki ad\u0131mda olu\u015fturulan concrete aggregate s\u0131n\u0131f\u0131ndaki event&#8217;leri Event Store&#8217;da depolayabilmekte yahut depolanm\u0131\u015f olan event&#8217;leri tekrar elde edebilmekteyiz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class AggregateRepository\r\n    {\r\n        readonly IEventStoreConnection _connection;\r\n        public AggregateRepository(IEventStoreConnection connection)\r\n            =&gt; _connection = connection;\r\n        \/\/Olu\u015fturulan event'leri Event Store'a kaydeder.\r\n        public async Task SaveAsync&lt;T&gt;(T aggregate) where T : Aggregate, new()\r\n        {\r\n            List&lt;EventData&gt; events = aggregate.GetEvents\r\n                .Select(@event =&gt; new EventData(\r\n                    eventId: Guid.NewGuid(),\r\n                    type: @event.GetType().Name,\/\/type : Event Store'a kaydedilecek olan event'in t\u00fcr\u00fcn\u00fc s\u0131n\u0131f olarak bildiriyoruz.\r\n                    isJson: true,\r\n                    data: Encoding.UTF8.GetBytes(JsonSerializer.Serialize( \/\/Event json t\u00fcr\u00fcne serialize ediliyor.\r\n                        value: @event,\r\n                        inputType: @event.GetType(),\r\n                        new() { WriteIndented = true }\r\n                        )),\r\n                    metadata: Encoding.UTF8.GetBytes(@event.GetType().FullName))\/*metadata : Metadata olarak binary formatta ilgili\r\n event'in FullName bilgisini yani namespace ile birlikte full class ad\u0131n\u0131 tutmaktay\u0131z. Bu bilgiyi, event'leri 'Read Data Store'da\r\n g\u00fcncelleme yaparken hangi event'in ger\u00e7ekle\u015fti\u011fini ay\u0131rt edebilmek i\u00e7in kullanaca\u011f\u0131z. *\/\r\n                )\r\n                .ToList();\r\n\r\n            if (!events.Any())\r\n                return;\r\n\r\n            \/\/Event'ler g\u00f6nderiliyor...\r\n            await _connection.AppendToStreamAsync(aggregate.StreamName, ExpectedVersion.Any, events);\r\n            aggregate.GetEvents.Clear();\r\n        }\r\n        \/\/Event Store'dan belirtilen Stream'de ki event'leri getirir.\r\n        public async Task&lt;dynamic&gt; GetEvents(string streamName)\r\n        {\r\n            long nextSliceStart = 0L;\r\n            List&lt;ResolvedEvent&gt; events = new();\r\n            StreamEventsSlice readEvents = null;\r\n            do\r\n            {\r\n                readEvents = await _connection.ReadStreamEventsForwardAsync(\r\n                    stream: streamName,\r\n                    start: nextSliceStart,\r\n                    count: 4096,\r\n                    resolveLinkTos: true\r\n                    );\r\n\r\n                if (readEvents.Events.Length &gt; 0)\r\n                    events.AddRange(readEvents.Events);\r\n\r\n                nextSliceStart = readEvents.NextEventNumber;\r\n            } while (!readEvents.IsEndOfStream);\r\n            return events.Select(@event =&gt; new\r\n            {\r\n                @event.Event.EventNumber,\r\n                @event.Event.EventType,\r\n                @event.Event.Created,\r\n                @event.Event.EventId,\r\n                @event.Event.EventStreamId,\r\n                Data = JsonSerializer.Deserialize(\r\n                    json: Encoding.UTF8.GetString(@event.Event.Data),\r\n                    returnType: Type.GetType(Encoding.UTF8.GetString(@event.Event.Metadata)) \/*returnType : Yukar\u0131da 'SaveAsync'\r\n metodunda metadata olarak tutulan event class'\u0131n\u0131n tam ad\u0131, burada ilgili event'in \u00f6zg\u00fcn s\u0131n\u0131f\u0131na d\u00f6n\u00fc\u015ft\u00fcr\u00fcl\u00fcrken kullan\u0131lmaktad\u0131r.*\/\r\n                    ),\r\n                Metadata = Encoding.UTF8.GetString(@event.Event.Metadata)\r\n            });\r\n        }\r\n        \/\/Event'lerin uyguland\u0131\u011f\u0131 User datas\u0131n\u0131n son halini getirir.\r\n        public async Task&lt;User&gt; GetData(string streamName)\r\n        {\r\n            dynamic events = await GetEvents(streamName);\r\n            User user = new();\r\n            foreach (var @event in events)\r\n            {\r\n                switch (@event.Data)\r\n                {\r\n                    case UserCreated o:\r\n                        user.Id = o.UserId;\r\n                        user.Name = o.Name;\r\n                        user.UserName = o.UserName;\r\n                        user.Email = o.Email;\r\n                        user.EmailApprove = o.EmailApprove;\r\n                        break;\r\n                    case UserNameChanged o:\r\n                        user.Name = o.NewName;\r\n                        break;\r\n                    case UserEmailApproved o:\r\n                        user.EmailApprove = true;\r\n                        break;\r\n                }\r\n            }\r\n            return user;\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funa g\u00f6z atarsan\u0131z e\u011fer sat\u0131r aral\u0131klar\u0131nda a\u00e7\u0131klama yap\u0131lm\u0131\u015f olsa da iki hasbihalde bulunmadan ge\u00e7mek \u00e7okta makale adab\u0131na uygun olmayaca\u011f\u0131 i\u00e7in \u00f6zet mahiyetinde bir ka\u00e7 c\u00fcmle karalamakta fayda vard\u0131r. G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere bu aggregate repository s\u0131n\u0131f\u0131 \u00f6nceden de bahsedildi\u011fi gibi concrete aggregate nesnesindeki event&#8217;leri Event Store&#8217;a g\u00f6ndermekte ve ihtiya\u00e7 do\u011frultusunda tekrar okuma i\u015flemini ger\u00e7ekle\u015ftirmektedir. Burada en \u00f6nemli noktalardan birisi &#8216;SaveAsync&#8217; fonksiyonundaki &#8216;metadata&#8217; bilgisidir. Bu, eklenecek olan event&#8217;in class t\u00fcr\u00fcn\u00fc tam olarak tutmakta ve ihtiya\u00e7 do\u011frultusunda bu t\u00fcre ilgili event&#8217;i d\u00f6n\u00fc\u015ft\u00fcrebilmek i\u00e7in tekrar kullan\u0131lmaktad\u0131r. Bu d\u00f6n\u00fc\u015f\u00fcm\u00fc de &#8216;GetEvents&#8217; metodu i\u00e7erisindeki <em><strong>60.<\/strong><\/em> sat\u0131rda a\u00e7\u0131k\u00e7a g\u00f6rebilmekteyiz.<\/p>\n<p>&#8216;GetData&#8217; metodu ise ilgili event&#8217;lerin mevcudiyetteki dataya olan etkisini instance olarak g\u00f6sterebilmek i\u00e7in ekstradan olu\u015fturulmu\u015f \u00f6rnek bir fonksiyondur. Haliyle bu fonksiyondan yola \u00e7\u0131karak &#8216;Read Data Store&#8217; taraf\u0131nda hangi yolla bir g\u00fcncelleme i\u015flemi yap\u0131laca\u011f\u0131n\u0131n ipucunu vermi\u015f bulunmaktay\u0131z. Bu konuya dair sonraki makalemizde daha geni\u015f kapsaml\u0131 bir incelemede bulunuyor olaca\u011f\u0131m\u0131zdan dolay\u0131 \u015fimdilik teknik a\u00e7\u0131dan bu kadar bir numune yeterlidir kanaatindeyim.\n<\/li>\n<li><strong>Ad\u0131m 7<\/strong> <em style=\"color:green;\">Startup.cs Dosyas\u0131nda Gerekli Konfig\u00fcrasyonlar<\/em><br \/>\nYap\u0131lan bunca \u00e7al\u0131\u015fmadan sonra Asp.NET Core API uygulamas\u0131nda concrete aggregate ve aggregate repository s\u0131n\u0131flar\u0131n\u0131n servis olarak eklenebilmesi ve temel Event Store konfig\u00fcrasyonlar\u0131n\u0131n yap\u0131labilmesi i\u00e7in &#8216;Startup.cs&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fma yap\u0131lmal\u0131d\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public Startup(IConfiguration configuration)\r\n        {\r\n            Configuration = configuration;\r\n        }\r\n\r\n        public IConfiguration Configuration { get; }\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;API_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.AddSingleton&lt;AggregateRepository&gt;();\r\n            services.AddSingleton&lt;UserAggregate&gt;();\r\n\r\n            services.AddControllers();\r\n            .\r\n            .\r\n            .\r\n        }\r\n\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n        {\r\n            .\r\n            .\r\n            .\r\n        }\r\n    }\r\n<\/pre>\n<\/li>\n<li><strong>Ad\u0131m 8<\/strong> <em style=\"color:green;\">Controller&#8217;\u0131n Geli\u015ftirilmesi<\/em><br \/>\nSon olarak \u00f6nceden olu\u015fturdu\u011fumuz &#8216;UsersController&#8217; s\u0131n\u0131f\u0131n\u0131n i\u00e7eri\u011fini a\u015fa\u011f\u0131daki gibi tasarlay\u0131n\u0131z.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    &#x5B;Route(&quot;api\/&#x5B;controller]&quot;)]\r\n    &#x5B;ApiController]\r\n    public class UsersController : ControllerBase\r\n    {\r\n        readonly AggregateRepository _aggregateRepository;\r\n        readonly UserAggregate _userAggregate;\r\n        public UsersController(AggregateRepository aggregateRepository, UserAggregate userAggregate)\r\n        {\r\n            _aggregateRepository = aggregateRepository;\r\n            _userAggregate = userAggregate;\r\n        }\r\n        &#x5B;HttpPost(&quot;&#x5B;action]&quot;)]\r\n        public async Task&lt;IActionResult&gt; Create(CreateUserVM model)\r\n        {\r\n            int userId = 100;\r\n            _userAggregate.SetStreamName($&quot;user-{userId}&quot;);\r\n            _userAggregate.Created(new()\r\n            {\r\n                Id = userId,\r\n                Email = model.Email,\r\n                Name = model.Name,\r\n                UserName = model.UserName\r\n            });\r\n\r\n            await _aggregateRepository.SaveAsync(_userAggregate);\r\n            return StatusCode((int)HttpStatusCode.Created);\r\n        }\r\n        &#x5B;HttpPut(&quot;&#x5B;action]&quot;)]\r\n        public async Task&lt;IActionResult&gt; UpdateName(UpdateNameUserVM model)\r\n        {\r\n            _userAggregate.NameChanged(model.Name, model.Id);\r\n\r\n            await _aggregateRepository.SaveAsync(_userAggregate);\r\n            return StatusCode((int)HttpStatusCode.OK);\r\n\r\n        }\r\n\r\n        &#x5B;HttpPut(&quot;&#x5B;action]&quot;)]\r\n        public async Task&lt;IActionResult&gt; EmailApprove(EmailApproveUserVM model)\r\n        {\r\n            _userAggregate.EmailApproved(model.Id);\r\n\r\n            await _aggregateRepository.SaveAsync(_userAggregate);\r\n            return StatusCode((int)HttpStatusCode.OK);\r\n\r\n        }\r\n        &#x5B;HttpGet(&quot;&#x5B;action]\/{streamName}&quot;)]\r\n        public async Task&lt;IActionResult&gt; GetEvents(string streamName)\r\n        {\r\n            dynamic events = await _aggregateRepository.GetEvents($&quot;user-{streamName}&quot;);\r\n            return Ok(events);\r\n        }\r\n\r\n        &#x5B;HttpGet(&quot;&#x5B;action]\/{streamName}&quot;)]\r\n        public async Task&lt;IActionResult&gt; GetData(string streamName)\r\n        {\r\n            User user = await _aggregateRepository.GetData($&quot;user-{streamName}&quot;);\r\n            return Ok(user);\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131da kullan\u0131lan viewmodel s\u0131n\u0131flar\u0131n\u0131n i\u00e7eri\u011fi a\u015fa\u011f\u0131daki gibi olacakt\u0131r:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class CreateUserVM\r\n    {\r\n        public string Name { get; set; }\r\n        public string UserName { get; set; }\r\n        public string Email { get; set; }\r\n    }\r\n<\/pre>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdateNameUserVM\r\n    {\r\n        public int Id { get; set; }\r\n        public string Name { get; set; }\r\n    }\r\n<\/pre>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class EmailApproveUserVM\r\n    {\r\n        public int Id { get; set; }\r\n    }\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>Evet, bu sat\u0131rlara sa\u011f salim ula\u015fabildiyseniz e\u011fer hedeflenen event sourcing yap\u0131lanmas\u0131n\u0131 ba\u015far\u0131yla in\u015fa etmi\u015fsiniz demektir \ud83d\ude42 \u015eimdi s\u0131ra geli\u015ftirilen bu uygulamay\u0131 test etmeye gelmi\u015ftir.<\/p>\n<h4>Uygulamay\u0131 \u00c7al\u0131\u015ft\u0131rma ve Test Etme<\/h4>\n<p>Uygulamay\u0131 derleyip \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda &#8216;Startup.cs&#8217; dosyas\u0131nda yapt\u0131\u011f\u0131m\u0131z konfig\u00fcrasyonlara istinaden Event Store&#8217;a ba\u011flant\u0131 ger\u00e7ekle\u015ftirilmekte, dolay\u0131s\u0131yla bu ba\u011flant\u0131 ilgili tool&#8217;un &#8216;Connections&#8217; k\u0131sm\u0131nda a\u015fa\u011f\u0131daki gibi g\u00f6r\u00fclebilmektedir.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-1.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"573\" height=\"140\" class=\"aligncenter size-full wp-image-21735\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-1.png 573w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-1-300x73.png 300w\" sizes=\"auto, (max-width: 573px) 100vw, 573px\" \/><\/a><\/p>\n<p>Velhas\u0131l, \u015fimdi geli\u015ftirdi\u011fimiz API&#8217;da ki &#8216;UsersController&#8217;a Postman \u00fczerinden s\u0131ras\u0131yla istekler g\u00f6nderelim ve ger\u00e7ekle\u015ftirilen event&#8217;lere istinaden mevcudiyetteki datan\u0131n \u00fczerindeki geli\u015fimi &#8216;GetData&#8217; action&#8217;\u0131na istek g\u00f6ndererek g\u00f6zlemleyelim. Nihayetindeki bu g\u00f6zlem esas\u0131nda &#8216;Read Data Store&#8217;a izafen veriye dair s\u00fcre\u00e7teki de\u011fi\u015fimi g\u00f6rmemiz i\u00e7in faydal\u0131 olacakt\u0131r.<\/p>\n<ul>\n<li><em style=\"color:purple;\">Kullan\u0131c\u0131 ekleme\/olu\u015fturma<\/em><br \/>\nEndpoint : <code style=\"color:red;font-size:12px;\"><strong>https:\/\/localhost:5001\/api\/users\/create<\/strong><\/code><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-2.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"756\" height=\"265\" class=\"aligncenter size-full wp-image-21739\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-2.png 756w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-2-300x105.png 300w\" sizes=\"auto, (max-width: 756px) 100vw, 756px\" \/><\/a>GetData :<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-3.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"737\" height=\"262\" class=\"aligncenter size-full wp-image-21740\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-3.png 737w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-3-300x107.png 300w\" sizes=\"auto, (max-width: 737px) 100vw, 737px\" \/><\/a>Mevcut data kullan\u0131c\u0131 eklendi\u011fi i\u00e7in ilk ve default de\u011ferlerle olu\u015fturulmu\u015ftur.\n<\/li>\n<li><em style=\"color:purple;\">Kullan\u0131c\u0131 ad\u0131 de\u011fi\u015ftirme<\/em><br \/>\nEndpoint : <code style=\"color:red;font-size:12px;\"><strong>https:\/\/localhost:5001\/api\/users\/updatename<\/strong><\/code><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-4.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"749\" height=\"265\" class=\"aligncenter size-full wp-image-21743\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-4.png 749w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-4-300x106.png 300w\" sizes=\"auto, (max-width: 749px) 100vw, 749px\" \/><\/a>GetData :<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-5.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"748\" height=\"248\" class=\"aligncenter size-full wp-image-21744\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-5.png 748w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-5-300x99.png 300w\" sizes=\"auto, (max-width: 748px) 100vw, 748px\" \/><\/a>Yap\u0131lan isim g\u00fcncellemesinden sonra bu de\u011fi\u015fiklik g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ilgili data&#8217;ya yans\u0131m\u0131\u015ft\u0131r. Hatta bir kere daha de\u011fi\u015fiklik yaparsak bunun &#8216;Read Data Store&#8217;da ki dataya yans\u0131d\u0131\u011f\u0131n\u0131 daha net g\u00f6receksiniz.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-6.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"743\" height=\"261\" class=\"aligncenter size-full wp-image-21745\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-6.png 743w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-6-300x105.png 300w\" sizes=\"auto, (max-width: 743px) 100vw, 743px\" \/><\/a><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-7.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-7.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"748\" height=\"257\" class=\"aligncenter size-full wp-image-21746\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-7.png 748w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-7-300x103.png 300w\" sizes=\"auto, (max-width: 748px) 100vw, 748px\" \/><\/a>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere bu seferde &#8216;K\u00fcr\u015fad&#8217;dan &#8216;Elif&#8217;e bir de\u011fi\u015fim yapt\u0131k ve ilgili data&#8217;da bu de\u011fi\u015fimi g\u00f6rmekteyiz.\n<\/li>\n<li><em style=\"color:purple;\">Kullan\u0131c\u0131 email onaylama<\/em><br \/>\nEndpoint : <code style=\"color:red;font-size:12px;\"><strong>https:\/\/localhost:5001\/api\/users\/emailapprove<\/strong><\/code><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-8.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-8.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"748\" height=\"218\" class=\"aligncenter size-full wp-image-21748\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-8.png 748w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-8-300x87.png 300w\" sizes=\"auto, (max-width: 748px) 100vw, 748px\" \/><\/a>GetData :<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-9.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-9.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"745\" height=\"185\" class=\"aligncenter size-full wp-image-21749\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-9.png 745w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-9-300x74.png 300w\" sizes=\"auto, (max-width: 745px) 100vw, 745px\" \/><\/a>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere ilgili kullan\u0131c\u0131n\u0131n email&#8217;i onaylanm\u0131\u015ft\u0131r.\n<\/li>\n<\/ul>\n<p>\u015eimdi son olarak 100 id de\u011ferine sahip kullan\u0131c\u0131 data&#8217;s\u0131n\u0131n t\u00fcm s\u00fcre\u00e7te ya\u015fad\u0131\u011f\u0131 de\u011fi\u015fimleri g\u00f6rebilmek i\u00e7in elimizdeki t\u00fcm event&#8217;leri hem API hem de Event Store \u00fczerinden okuyal\u0131m.<\/p>\n<table>\n<thead>\n<tr>\n<th>API<\/th>\n<th>Event Store<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"vertical-align:top;\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-10.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-10.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"542\" height=\"791\" class=\"aligncenter size-full wp-image-21753\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-10.png 542w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-10-206x300.png 206w\" sizes=\"auto, (max-width: 542px) 100vw, 542px\" \/><\/a><\/td>\n<td style=\"vertical-align:top;\"><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-11.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-11.png\" alt=\"Asp.NET Core + Event Store \u0130le Event Sourcing Uygulamas\u0131(\u00d6rneklendirme)\" width=\"364\" height=\"944\" class=\"aligncenter size-full wp-image-21754\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-11.png 364w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/Asp.NET-Core-Event-Store-Ile-Event-Sourcing-UygulamasiOrneklendirme-11-116x300.png 116w\" sizes=\"auto, (max-width: 364px) 100vw, 364px\" \/><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Yukar\u0131daki g\u00f6rsellere g\u00f6z atarak event sourcing&#8217;in esas\u0131nda bir veri i\u00e7in ne kadar anlaml\u0131 pattern oldu\u011funu g\u00f6rebilmektesiniz. Nihayetinde elimizdeki kullan\u0131c\u0131 verisinin \u015fu anki durumunu, zahiri olarak g\u00f6rd\u00fc\u011f\u00fcm\u00fczden daha \u00e7ok s\u00fcre\u00e7te ge\u00e7irdi\u011fi evrelerden ibaret bir b\u00fct\u00fcn oldu\u011funu g\u00f6rebilmekteyiz.<\/p>\n<p>Evet&#8230; B\u00f6ylece bu i\u00e7eri\u011fimizde de event sourcing in\u015fas\u0131n\u0131 g\u00fczel bir yap\u0131lanmayla ele alm\u0131\u015f bulunuyoruz. Bir sonraki i\u00e7eri\u011fimizde muhtemelen, messaging yap\u0131lanmas\u0131ndan istifade ederek &#8216;Read Data Store&#8217; olarak se\u00e7ti\u011fimiz herhangi bir NoSQL veritaban\u0131na(MongoDB yahut Couchbase) event&#8217;lar\u0131 i\u015flemeyi ele al\u0131yor olaca\u011f\u0131z.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek uygulamay\u0131 indirebilmek i\u00e7in <a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2021\/05\/EventSourcing_Example_With_EventStore.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, \u00d6nceki, .NET Core Ortam\u0131nda \u2018Event Store\u2019 \u0130le Event Sourcing Yap\u0131lanmas\u0131 ba\u015fl\u0131kl\u0131 makalemde Event Sourcing yap\u0131lanmas\u0131 i\u00e7in Event Store ile yap\u0131lmas\u0131 gereken temel ayarlardan ve ba\u011flant\u0131 konfig\u00fcrasyonlar\u0131ndan bahsetmi\u015ftik. Bu i\u00e7eri\u011fimizde ise bir Asp.NET Core&#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":21690,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2739,3573],"tags":[4253,4252,4255,4254,4256],"class_list":["post-21681","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-microservices","tag-asp-net-core-event-sourcing","tag-asp-net-core-event-store","tag-event-sourcing-with-event-store","tag-event-store-event-sourcing","tag-eventstore-client"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21681","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=21681"}],"version-history":[{"count":69,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21681\/revisions"}],"predecessor-version":[{"id":21767,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/21681\/revisions\/21767"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/21690"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=21681"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=21681"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=21681"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}