{"id":33839,"date":"2019-10-31T21:54:56","date_gmt":"2019-10-31T18:54:56","guid":{"rendered":"https:\/\/prohoster.info\/blog\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov\/"},"modified":"2019-10-31T21:54:56","modified_gmt":"2019-10-31T18:54:56","slug":"objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sq\/blog\/novosti-interneta\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov","title":{"rendered":"ObjectRepository \u2014 .NET n\u00eb memorandum t\u00eb depozit\u00ebs p\u00ebr projektet tuaja t\u00eb sht\u00ebpis\u00eb","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<h2 id=\"zachem-hranit-vse-dannye-v-pamyati\">Pse t\u00eb ruajm\u00eb t\u00eb gjith\u00eb t\u00eb dh\u00ebnat n\u00eb kujtes\u00eb?<\/h2>\n<p><\/p>\n<p>P\u00ebr ruajtjen e t\u00eb dh\u00ebnave t\u00eb faqes ose backend-it, shumica e njer\u00ebzve t\u00eb sh\u00ebndosh\u00eb do t\u00eb zgjedhin nj\u00eb baz\u00eb t\u00eb dh\u00ebnash SQL.\u00a0<\/p>\n<p><\/p>\n<p>Por ndonj\u00ebher\u00eb na vjen n\u00eb mendje se modeli i t\u00eb dh\u00ebnave nuk \u00ebsht\u00eb i p\u00ebrshtatsh\u00ebm p\u00ebr SQL: p\u00ebr shembull, kur ndihmojm\u00eb n\u00eb nd\u00ebrtimin e k\u00ebrkimeve ose t\u00eb nj\u00eb grafi social, k\u00ebrkohet k\u00ebrkimi p\u00ebrmes lidhjeve komplekse midis objekteve.\u00a0<\/p>\n<p><\/p>\n<p><strong>Situata m\u00eb e keqe \u00ebsht\u00eb kur punoni n\u00eb nj\u00eb ekip dhe kolegu nuk di t\u00eb nd\u00ebrtoj\u00eb k\u00ebrkesa t\u00eb shpejta. Sa koh\u00eb keni shpenzuar p\u00ebr t\u00eb zgjidhur problemet N+1 dhe p\u00ebr nd\u00ebrtimin e indekseve t\u00eb tjera, q\u00eb SELECT n\u00eb faqen kryesore t\u00eb punoj\u00eb brenda nj\u00eb kohe t\u00eb arsyeshme?<\/strong><\/p>\n<p><\/p>\n<p>Nj\u00eb qasje tjet\u00ebr e njohur \u00ebsht\u00eb NoSQL. Disa vjet m\u00eb par\u00eb kishte shum\u00eb hype rreth k\u00ebtij subjekti \u2014 p\u00ebr \u00e7do rast t\u00eb p\u00ebrshtatsh\u00ebm, ne vendosnim MongoDB dhe g\u00ebzonim p\u00ebrgjigjet n\u00eb form\u00eb dokumentesh JSON. <em>(megjithat\u00eb, sa \"k\u00ebmb\u00eb\" duhej t\u00eb vendosnim p\u00ebr shkak t\u00eb lidhjeve ciklike n\u00eb dokumente?)<\/em>.<\/p>\n<p><\/p>\n<p>Un\u00eb propozoj t\u00eb provojm\u00eb nj\u00eb qasje tjet\u00ebr \u2014 pse t\u00eb mos p\u00ebrpiqemi t\u00eb ruajm\u00eb t\u00eb gjith\u00eb t\u00eb dh\u00ebnat n\u00eb kujtes\u00ebn e aplikacionit, duke ruajtur rast\u00ebsisht n\u00eb nj\u00eb depo t\u00eb jashtme (file, baz\u00eb t\u00eb dh\u00ebnash t\u00eb larg\u00ebt)?\u00a0<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Kujtesa \u00ebsht\u00eb b\u00ebr\u00eb e lir\u00eb dhe pothuajse t\u00eb gjitha t\u00eb dh\u00ebnat e shumic\u00ebs s\u00eb projekteve t\u00eb vogla dhe t\u00eb mesme do t\u00eb futen n\u00eb 1 GB kujtes\u00eb. <em>(P\u00ebr shembull, projekti im i preferuar n\u00eb sht\u00ebpi \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/DiverOfDark\/BudgetTracker\">nj\u00eb ndjek\u00ebs financiar<\/a><\/noindex>, i cili ndjek statistik\u00ebn dhe historin\u00eb e shpenzimeve, bilanceve dhe transaksioneve p\u00ebr nj\u00eb periudh\u00eb nj\u00eb vit e gjysm\u00eb konsumon vet\u00ebm 45 MB kujtes\u00eb.)<\/em><\/p>\n<p><\/p>\n<p>Avantazhet:<\/p>\n<p><\/p>\n<ul>\n<li>Qasja n\u00eb t\u00eb dh\u00ebna b\u00ebhet m\u00eb e leht\u00eb \u2014 nuk nevojitet t\u00eb mendoni p\u00ebr k\u00ebrkesat, ngarkimin e ngadalsh\u00ebm, ve\u00e7orit\u00eb e ORM, puna b\u00ebhet me objekte C# t\u00eb zakonshme;<\/li>\n<li>Nuk ka probleme t\u00eb lidhura me qasjen nga pika t\u00eb ndryshme;<\/li>\n<li>Shum\u00eb shpejt \u2014 nuk ka k\u00ebrkesa rrjeti, nuk ka p\u00ebrkthim t\u00eb kodit n\u00eb gjuh\u00ebn e k\u00ebrkesave, nuk nevojitet (de)serializimi i objekteve;<\/li>\n<li>\u00cbsht\u00eb e pranueshme t\u00eb ruhen t\u00eb dh\u00ebnat n\u00eb \u00e7do form\u00eb \u2014 qoft\u00eb n\u00eb XML n\u00eb disk, qoft\u00eb n\u00eb SQL Server, qoft\u00eb n\u00eb Azure Table Storage.<\/li>\n<\/ul>\n<p><\/p>\n<p>Disavantazhet:<\/p>\n<p><\/p>\n<ul>\n<li>Humbet skalimi horizontal, dhe si pasoj\u00eb nuk mund t\u00eb b\u00ebni nj\u00eb vendosje pa koh\u00eb shk\u00ebputjeje;<\/li>\n<li>N\u00ebse aplikacioni bie \u2014 mund t\u00eb humbni pjes\u00ebrisht t\u00eb dh\u00ebnat. <em>(Por aplikacioni yn\u00eb kurr\u00eb nuk bie, e v\u00ebrteta?)<\/em><\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"kak-eto-rabotaet\">Si funksionon?<\/h2>\n<p><\/p>\n<p>Algoritmi \u00ebsht\u00eb si m\u00eb posht\u00eb:<\/p>\n<p><\/p>\n<ul>\n<li>N\u00eb fillim krijohet nj\u00eb lidhje me depozitat e t\u00eb dh\u00ebnave, dhe ndodh ngarkimi i t\u00eb dh\u00ebnave;<\/li>\n<li>Nd\u00ebrtohet nj\u00eb model objekti, indekset fillestare dhe indekset e marr\u00ebdh\u00ebnieve (1:1, 1:M\u00eb shum\u00eb);<\/li>\n<li>Krijohet nj\u00eb abonim p\u00ebr ndryshimet n\u00eb pronat e objekteve (INotifyPropertyChanged) dhe p\u00ebr shtimin ose heqjen e elementeve n\u00eb koleksion (INotifyCollectionChanged);<\/li>\n<li>Kur ndodh nj\u00eb skenar \u2014 objekti q\u00eb \u00ebsht\u00eb ndryshuar, shtohet n\u00eb radh\u00ebn p\u00ebr t\u00eb shkruar n\u00eb depozit\u00ebn e t\u00eb dh\u00ebnave;<\/li>\n<li>Her\u00eb pas here (p\u00ebrmes nj\u00eb timer-i) n\u00eb nj\u00eb thread t\u00eb prapavij\u00ebs ruhen ndryshimet n\u00eb depozit\u00eb;<\/li>\n<li>Kur dilni nga aplikacioni gjithashtu ruhen ndryshimet n\u00eb depozit\u00eb.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"primer-koda\">Shembulli i kodit<\/h2>\n<p>\n<b class=\"spoiler_title\">Shtoni var\u00ebsit\u00eb e nevojshme<\/b><\/p>\n<pre><code class=\"cs\">\/\/ \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\nInstall-Package OutCode.EscapeTeams.ObjectRepository\n\u00a0 \u00a0\u00a0\n\/\/ \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\n\/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.\nInstall-Package OutCode.EscapeTeams.ObjectRepository.File\nInstall-Package OutCode.EscapeTeams.ObjectRepository.LiteDb\nInstall-Package OutCode.EscapeTeams.ObjectRepository.AzureTableStorage\n\u00a0 \u00a0\u00a0\n\/\/ \u041e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e - \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f Hangfire\n\/\/ Install-Package OutCode.EscapeTeams.ObjectRepository.Hangfire<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">P\u00ebrshkruani modelin e t\u00eb dh\u00ebnave q\u00eb do t\u00eb ruhet n\u00eb depozit\u00eb<\/b><\/p>\n<pre><code class=\"cs\">public class ParentEntity : BaseEntity\n{\n    public ParentEntity(Guid id) =&gt; Id = id;\n}\n    \npublic class ChildEntity : BaseEntity\n{\n    public ChildEntity(Guid id) =&gt; Id = id;\n    public Guid ParentId { get; set; }\n    public string Value { get; set; }\n}<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">Pastaj modelin e objektit:<\/b><\/p>\n<pre><code class=\"cs\">public class ParentModel : ModelBase\n{\n    public ParentModel(ParentEntity entity)\n    {\n        Entity = entity;\n    }\n    \n    public ParentModel()\n    {\n        Entity = new ParentEntity(Guid.NewGuid());\n    }\n    \n    public Guid? NullableId =&gt; null;\n    \n    \/\/ Shembull lidhjeje 1:M\u00eb shum\u00eb\n    public IEnumerable Children =&gt; Multiple(x =&gt; x.ParentId);\n    \n    protected override BaseEntity Entity { get; }\n}\n    \npublic class ChildModel : ModelBase\n{\n    private ChildEntity _childEntity;\n    \n    public ChildModel(ChildEntity entity)\n    {\n        _childEntity = entity;\n    }\n    \n    public ChildModel() \n    {\n        _childEntity = new ChildEntity(Guid.NewGuid());\n    }\n    \n    public Guid ParentId\n    {\n        get =&gt; _childEntity.ParentId;\n        set =&gt; UpdateProperty(() =&gt; _childEntity.ParentId, value);\n    }\n    \n    public string Value\n    {\n        get =&gt; _childEntity.Value;\n        set =&gt; UpdateProperty(() =&gt; _childEntity.Value, value);\n    }\n    \n    \/\/ Qasje me k\u00ebrkimin p\u00ebrmes indeksit\n    public ParentModel Parent =&gt; Single(ParentId);\n    \n    protected override BaseEntity Entity =&gt; _childEntity;\n}<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">Dhe s\u00eb fundi klasa-repozit\u00eb p\u00ebr qasjen n\u00eb t\u00eb dh\u00ebna:<\/b><\/p>\n<pre><code class=\"cs\">public class MyObjectRepository : ObjectRepositoryBase\n{\n    public MyObjectRepository(IStorage storage) : base(storage, NullLogger.Instance)\n    {\n        IsReadOnly = true; \/\/ P\u00ebr testet, lejon t\u00eb mos ruhen ndryshime n\u00eb baz\u00eb\n    \n        AddType((ParentEntity x) =&gt; new ParentModel(x));\n        AddType((ChildEntity x) =&gt; new ChildModel(x));\n    \n        \/\/ N\u00ebse p\u00ebrdoret Hangfire dhe \u00ebsht\u00eb e nevojshme t\u00eb ruhen model t\u00eb dh\u00ebnash p\u00ebr Hangfire n\u00eb ObjectRepository\n        \/\/ this.RegisterHangfireScheme();  \n    \n        Initialize();\n    }\n}<\/code><\/pre>\n<p><\/p>\n<p>Krijojm\u00eb nj\u00eb instanc\u00eb t\u00eb ObjectRepository:<\/p>\n<p><\/p>\n<pre><code class=\"cs\">var memory = new MemoryStream();\nvar db = new LiteDatabase(memory);\nvar dbStorage = new LiteDbStorage(db);\n    \nvar repository = new MyObjectRepository(dbStorage);\nawait repository.WaitForInitialize();<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">N\u00ebse n\u00eb projekt do t\u00eb p\u00ebrdoret HangFire<\/b><\/p>\n<pre><code class=\"cs\">public void ConfigureServices(IServiceCollection services, ObjectRepository objectRepository)\n{\n    services.AddHangfire(s =&gt; s.UseHangfireStorage(objectRepository));\n}<\/code><\/pre>\n<p><\/p>\n<p>Shtimi i nj\u00eb objekti t\u00eb ri:<\/p>\n<p><\/p>\n<pre><code class=\"cs\">var newParent = new ParentModel()\nrepository.Add(newParent);<\/code><\/pre>\n<p><\/p>\n<p>Me k\u00ebt\u00eb thirrje, objekti <strong>ParentModel<\/strong> shto shto shqip shkon n\u00eb cache lokal dhe n\u00eb radh\u00eb p\u00ebr t\u00eb shkruar n\u00eb baz\u00eb t\u00eb dh\u00ebnash. Prandaj, kjo operacion zgjat O(1), dhe ky objekt mund t\u00eb p\u00ebrdoret menj\u00ebher\u00eb.<\/p>\n<p><\/p>\n<p>P\u00ebr shembull, p\u00ebr t\u00eb gjetur k\u00ebt\u00eb objekt n\u00eb depo dhe p\u00ebr t'u siguruar q\u00eb objekti i kthyer \u00ebsht\u00eb e nj\u00ebjta referenc\u00eb:<\/p>\n<p><\/p>\n<pre><code class=\"cs\">var parents = repository.Set();\nvar myParent = parents.Find(newParent.Id);\nAssert.IsTrue(ReferenceEquals(myParent, newParent));<\/code><\/pre>\n<p><\/p>\n<p>\u00c7far\u00eb ndodh n\u00eb t\u00eb nj\u00ebjt\u00ebn koh\u00eb? <em>Set()<\/em> kthen <em>TableDictionary<\/em>, q\u00eb p\u00ebrmban brenda vetes <em>ConcurrentDictionary<\/em> dhe ofron funksionalitete shtes\u00eb p\u00ebr indekset e par\u00eb dhe t\u00eb dyt\u00eb. Kjo lejon metoda p\u00ebr k\u00ebrkimin sipas Id (ose indekseve t\u00eb tjera t\u00eb p\u00ebrdoruesve) pa e kontrolluar t\u00eb gjitha objektet.<\/p>\n<p><\/p>\n<p>Gjat\u00eb shtimit t\u00eb objekteve n\u00eb <em>ObjectRepository<\/em> shtohen an\u00ebtar\u00ebsime mbi ndryshimin e pronave t\u00eb tyre, k\u00ebshtu q\u00eb \u00e7do ndryshim i pronave ka t\u00eb b\u00ebj\u00eb edhe me shtimin e k\u00ebtij objekti n\u00eb radh\u00eb p\u00ebr shkruan.\u00a0<br \/>\nP\u00ebrdit\u00ebsimi i pronave nga jasht\u00eb duket ashtu si puna me nj\u00eb objekt POCO:<\/p>\n<p><\/p>\n<pre><code class=\"cs\">myParent.Children.First().Property = \"Vlera e p\u00ebrdit\u00ebsuar\";<\/code><\/pre>\n<p><\/p>\n<p>Objekti mund t\u00eb hiqet n\u00eb k\u00ebto m\u00ebnyra:<\/p>\n<p><\/p>\n<pre><code class=\"cs\">repository.Remove(myParent);\nrepository.RemoveRange(otherParents);\nrepository.Remove(x =&gt; !x.Children.Any());<\/code><\/pre>\n<p><\/p>\n<p>Gjithashtu, objekti shtohet n\u00eb radh\u00ebn p\u00ebr fshirje.<\/p>\n<p><\/p>\n<h2 id=\"kak-rabotaet-sohranenie\">Si funksionon ruajtja?<\/h2>\n<p><\/p>\n<p><em>ObjectRepository<\/em> nd\u00ebrsa objekti t\u00eb jet\u00eb n\u00ebn v\u00ebzhgim (si shtim ose fshirje, ashtu edhe ndryshim pronash) nxit nj\u00eb ngjarje <em>ModelChanged<\/em>, p\u00ebr t\u00eb cil\u00ebn \u00ebsht\u00eb an\u00ebtar\u00ebsuar <em>IStorage<\/em>. Implementimet <em>IStorage<\/em> n\u00eb ngjarjen e riparimit <em>ModelChanged<\/em> grumbullojn\u00eb ndryshimet n\u00eb 3 radh\u00eb - p\u00ebr shtim, p\u00ebr p\u00ebrdit\u00ebsim, dhe p\u00ebr fshirje.<\/p>\n<p><\/p>\n<p>P\u00ebr m\u00eb tep\u00ebr, implementimet <em>IStorage<\/em> n\u00eb inicializim krijojn\u00eb nj\u00eb timer, i cili \u00e7do 5 sekonda th\u00ebrret ruajtjen e ndryshimeve.\u00a0<\/p>\n<p><\/p>\n<p><em>P\u00ebrve\u00e7 k\u00ebsaj, ekziston nj\u00eb API p\u00ebr thirrjen e forc\u00ebs s\u00eb ruajtjes: <strong>ObjectRepository.Save()<\/strong>.<\/em><\/p>\n<p><\/p>\n<p>Para \u00e7do ruajtjeje, fillimisht ndodh fshirja e operacioneve t\u00eb panevojshme nga radh\u00ebt (p.sh. duplikat t\u00eb ngjarjeve - kur objekti \u00ebsht\u00eb modifikuar dy her\u00eb ose shtimi\/fshirja e shpejt\u00eb e objekteve), dhe vet\u00ebm pastaj ndodh ruajtja.\u00a0<\/p>\n<p><\/p>\n<p><em>N\u00eb t\u00eb gjitha rastet, objekti aktual ruhet plot\u00ebsisht, prandaj \u00ebsht\u00eb e mundur t\u00eb ndodhi nj\u00eb situat\u00eb kur objektet ruhen n\u00eb nj\u00eb rend tjet\u00ebr sesa ndryshuan, duke p\u00ebrfshir\u00eb mund\u00ebsin\u00eb q\u00eb versionet m\u00eb t\u00eb reja t\u00eb objekteve ruhet m\u00eb von\u00eb se sa momenti i shtimit n\u00eb radh\u00eb.<\/em><\/p>\n<p><\/p>\n<h2 id=\"chto-est-eschyo\">\u00c7far\u00eb ka tjet\u00ebr?<\/h2>\n<p><\/p>\n<ul>\n<li>T\u00eb gjitha bibliotekat jan\u00eb t\u00eb bazuara n\u00eb .NET Standard 2.0. Mund t\u00eb p\u00ebrdoren n\u00eb \u00e7do projekt modern .NET.<\/li>\n<li>API \u00ebsht\u00eb i sigur\u00ebt p\u00ebr rrjedh\u00ebn. Koleksionet e brendshme jan\u00eb t\u00eb implementuara mbi baz\u00ebn e <em>ConcurrentDictionary<\/em>, menaxher\u00ebt e ngjarjeve kan\u00eb ose bllokime, ose nuk nevojiten.\u00a0<br \/>\nE vetmja gj\u00eb p\u00ebr t'u kujtuar - gjat\u00eb mbylljes s\u00eb aplikacionit t\u00eb thirret <em>ObjectRepository.Save();<\/em><\/li>\n<li>Indekset e rast\u00ebsishme (k\u00ebrkojn\u00eb unik\u00ebsi):<\/li>\n<\/ul>\n<p><\/p>\n<pre><code class=\"cs\">repository.Set().AddIndex(x =&gt; x.Value);\nrepository.Set().Find(x =&gt; x.Value, \"myValue\");<\/code><\/pre>\n<p><\/p>\n<h2 id=\"kto-eto-ispolzuet\">Kush e p\u00ebrdor k\u00ebt\u00eb?<\/h2>\n<p><\/p>\n<p>Personalisht, un\u00eb fillova ta p\u00ebrdor k\u00ebt\u00eb qasje n\u00eb t\u00eb gjitha projektet e mia t\u00eb hobit, sepse \u00ebsht\u00eb e leverdishme dhe nuk k\u00ebrkon shum\u00eb investim n\u00eb shkrimin e nj\u00eb sloj t\u00eb qasjes ndaj t\u00eb dh\u00ebnave ose krijimin e nj\u00eb infrastrukture t\u00eb r\u00ebnd\u00eb. P\u00ebr mua, zakonisht \u00ebsht\u00eb e mjaftueshme ruajtja e t\u00eb dh\u00ebnave n\u00eb litedb ose n\u00eb nj\u00eb skedar.\u00a0<\/p>\n<p><\/p>\n<p>Por n\u00eb t\u00eb kaluar\u00ebn, kur me ekipin krijuam startup-in e tashm\u00eb t\u00eb vdekur EscapeTeams (<em>mendoja se k\u00ebtu jan\u00eb parat\u00eb - por jo, p\u00ebrs\u00ebri p\u00ebrvoj\u00eb<\/em>) - e p\u00ebrdor\u00ebm p\u00ebr ruajtjen e t\u00eb dh\u00ebnave Azure Table Storage.<\/p>\n<p><\/p>\n<h2 id=\"plany-na-buduschee\">Planet p\u00ebr t\u00eb ardhmen<\/h2>\n<p><\/p>\n<p>D\u00ebshiroj t\u00eb rregulloj nj\u00eb nga disavantazhet kryesore t\u00eb k\u00ebtij qasje \u2014 skalimin horizontal. P\u00ebr k\u00ebt\u00eb nevojiten ose transaksione t\u00eb shp\u00ebrndara (sic!), ose t\u00eb pranohet nj\u00eb vendim i fort\u00eb se t\u00eb nj\u00ebjtat t\u00eb dh\u00ebna nga instancat e ndryshme nuk duhet t\u00eb ndryshojn\u00eb, ose le t\u00eb ndryshojn\u00eb sipas parimit \u2018kush \u00ebsht\u00eb i fundit \u2014 ai ka t\u00eb drejt\u00eb\u2019.<\/p>\n<p><\/p>\n<p>Nga pik\u00ebpamja teknike, un\u00eb shoh nj\u00eb skem\u00eb t\u00eb mundshme:<\/p>\n<p><\/p>\n<ul>\n<li>Ruaj n\u00eb vend t\u00eb modelit objektor EventLog dhe Snapshot<\/li>\n<li>T\u00eb gjej\u00eb instancat e tjera (shtoni n\u00eb cil\u00ebsimet p\u00ebrfundimtare t\u00eb t\u00eb gjitha instancave? zbulimi UDP? master\/slave?)<\/li>\n<li>T\u00eb riplikoj\u00eb midis instancave EventLog p\u00ebrmes ndonj\u00eb algoritmi konsensusi, p\u00ebr shembull RAFT.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ka nj\u00eb problem tjet\u00ebr q\u00eb m\u00eb shqet\u00ebson - \u00ebsht\u00eb fshirja kaskadive, ose zbulimi i rasteve t\u00eb fshirjes s\u00eb objekteve, t\u00eb cilat kan\u00eb referenca nga objekte t\u00eb tjera.\u00a0<\/p>\n<p><\/p>\n<h2 id=\"ishodnyy-kod\">Kod i burimit<\/h2>\n<p><\/p>\n<p>N\u00ebse e keni lexuar k\u00ebt\u00eb deri k\u00ebtu - at\u00ebher\u00eb mbetet vet\u00ebm t\u00eb lexoni kodin, mund ta gjeni n\u00eb GitHub:<br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/DiverOfDark\/ObjectRepository\">https:\/\/github.com\/DiverOfDark\/ObjectRepository<\/a><\/noindex><\/p>\n<p>Burimi: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/452232\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0417\u0430\u0447\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438? \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0430\u0439\u0442\u0430 \u0438\u043b\u0438 \u0431\u0435\u043a\u044d\u043d\u0434\u0430 \u043f\u0435\u0440\u0432\u044b\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0434\u0440\u0430\u0432\u043e\u043c\u044b\u0441\u043b\u044f\u0449\u0438\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 SQL \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.\u00a0 \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u044b\u0441\u043b\u044c \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f SQL: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0430 \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0441\u0432\u044f\u0437\u044f\u043c \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438.\u00a0 \u0425\u0443\u0436\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-33839","post","type-post","status-publish","format-standard","hentry","category-novosti-interneta"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0417\u0430\u0447\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438? \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0430\u0439\u0442\u0430 \u0438\u043b\u0438 \u0431\u0435\u043a\u044d\u043d\u0434\u0430 \u043f\u0435\u0440\u0432\u044b\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0434\u0440\u0430\u0432\u043e\u043c\u044b\u0441\u043b\u044f\u0449\u0438\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 SQL \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u044b\u0441\u043b\u044c \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f SQL: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0430 \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0441\u0432\u044f\u0437\u044f\u043c \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438. \u0425\u0443\u0436\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435,\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sq\/blog\/novosti-interneta\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"sq_AL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47ObjectRepository \u2014 .NET in-memory repository pattern \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0417\u0430\u0447\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438? \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0430\u0439\u0442\u0430 \u0438\u043b\u0438 \u0431\u0435\u043a\u044d\u043d\u0434\u0430 \u043f\u0435\u0440\u0432\u044b\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0434\u0440\u0430\u0432\u043e\u043c\u044b\u0441\u043b\u044f\u0449\u0438\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 SQL \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u044b\u0441\u043b\u044c \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f SQL: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0430 \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0441\u0432\u044f\u0437\u044f\u043c \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438. \u0425\u0443\u0436\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435,\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sq\/blog\/novosti-interneta\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:54:56+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:54:56+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47ObjectRepository \u2014 .NET n\u00eb-memorje model p\u00ebr ruajtjen p\u00ebr projektet tuaja sht\u00ebpiake | ProHoster","description":"Pse duhet t\u00eb ruani t\u00eb gjitha t\u00eb dh\u00ebnat n\u00eb memorie? P\u00ebr ruajtjen e t\u00eb dh\u00ebnave t\u00eb faqes ose backend, d\u00ebshira e par\u00eb e shumic\u00ebs s\u00eb njer\u00ebzve me mendje t\u00eb sh\u00ebndosh\u00eb do t\u00eb zgjedhte nj\u00eb baz\u00eb t\u00eb dh\u00ebnash SQL. Por nganj\u00ebher\u00eb n\u00eb mendje vjen ideja se modeli i t\u00eb dh\u00ebnave nuk \u00ebsht\u00eb i p\u00ebrshtatsh\u00ebm p\u00ebr SQL: p\u00ebr shembull, kur nd\u00ebrtoni k\u00ebrkimin ose nj\u00eb graf social, nevojitet k\u00ebrkim mbi lidhjet e komplikuara midis objekteve. Situata m\u00eb e keqe \u00ebsht\u00eb kur punoni n\u00eb grup,","canonical_url":"https:\/\/prohoster.info\/sq\/blog\/novosti-interneta\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sq_AL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47ObjectRepository \u2014 .NET in-memory repository pattern \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 | ProHoster","og:description":"\u0417\u0430\u0447\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438? \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0430\u0439\u0442\u0430 \u0438\u043b\u0438 \u0431\u0435\u043a\u044d\u043d\u0434\u0430 \u043f\u0435\u0440\u0432\u044b\u043c \u0436\u0435\u043b\u0430\u043d\u0438\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0437\u0434\u0440\u0430\u0432\u043e\u043c\u044b\u0441\u043b\u044f\u0449\u0438\u0445 \u043b\u044e\u0434\u0435\u0439 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 SQL \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u044b\u0441\u043b\u044c \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f SQL: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0430 \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0441\u0432\u044f\u0437\u044f\u043c \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438. \u0425\u0443\u0436\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0435,","og:url":"https:\/\/prohoster.info\/sq\/blog\/novosti-interneta\/objectrepository-net-in-memory-repository-pattern-dlya-vashih-domashnih-proektov","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:54:56+00:00","article:modified_time":"2019-10-31T18:54:56+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"33839","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 16:56:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:32:27","updated":"2026-01-21 16:56:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/33839","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/comments?post=33839"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/33839\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media?parent=33839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/categories?post=33839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/tags?post=33839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}