{"id":391,"date":"2015-08-06T01:06:15","date_gmt":"2015-08-05T22:06:15","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=391"},"modified":"2015-08-06T01:06:41","modified_gmt":"2015-08-05T22:06:41","slug":"generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/","title":{"rendered":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak"},"content":{"rendered":"<p>Merhaba arkada\u015flar, bu makalemde sizlerle <strong>Generic\u00a0Repository<\/strong> ve <strong>Unit of Work<\/strong>\u00a0kurumsal tasar\u0131m kal\u0131plar\u0131n\u0131\u00a0uygulayarak temel bir <strong>alt yap\u0131 (infrastructure)<\/strong> tasarlayaca\u011f\u0131z. Tasarlama s\u0131ras\u0131nda Entity Framework&#8217;den yararlanarak <strong>code first<\/strong>\u00a0yakla\u015f\u0131m\u0131 ile geli\u015ftirece\u011fiz. Tabi ki alt yap\u0131m\u0131z <strong>ORM ba\u011f\u0131ms\u0131z (independent)<\/strong> olacak.<\/p>\n<p>Alt yap\u0131m\u0131z\u0131 geli\u015ftirirken\u00a0makul bir seviyede <strong>s\u0131k\u0131 s\u0131k\u0131ya ba\u011fl\u0131 (tight coupled)<\/strong> olmadan \u00a0<strong>gev\u015fek ba\u011flanm\u0131\u015f (loosely coupled)<\/strong> bir \u015fekilde geli\u015ftirmeye \u00e7al\u0131\u015faca\u011f\u0131z ki, gerek <strong>unit test<\/strong>&#8216;ler olsun gerekse de ileride geli\u015ftirece\u011fimiz bir mod\u00fcl i\u00e7in k\u0131r\u0131lma noktas\u0131na gelmeden, esnek bir \u015fekilde entegre\u00a0edebilmek i\u00e7in <strong>dependency inversion (ba\u011f\u0131ml\u0131l\u0131\u011f\u0131n ters \u00e7evirilmesi)<\/strong> prensibinden faydalanarak alt yap\u0131m\u0131z\u0131 esnek ve tekrar kullan\u0131labilir bir \u015fekilde tasarlayaca\u011f\u0131z.<\/p>\n<p>Alt yap\u0131m\u0131z\u0131 tasarlamaya ba\u015flamadan \u00f6nce bu iki kurumsal tasar\u0131m kal\u0131b\u0131n\u0131\u00a0bir tan\u0131mlayal\u0131m.<\/p>\n<h2>Repository Pattern Nedir?<\/h2>\n<p>Bu desenin temelinde yatan as\u0131l ama\u00e7;<\/p>\n<blockquote><p>Veritaban\u0131na veri ekleme, g\u00fcncelleme ve okuma\u00a0gibi <strong>CRUD (Create Read Update Delete)<\/strong> i\u015flemlerimiz i\u00e7in olu\u015fturmu\u015f oldu\u011fumuz\u00a0kodlar\u0131n tekrar kullan\u0131labilirli\u011fini sa\u011flamakt\u0131r.<\/p><\/blockquote>\n<p>Yaz\u0131l\u0131m geli\u015ftirmede, belkide en \u00f6nemli prensiplerden birisi olan <strong>DRY (Don&#8217;t repeat yourself)\u00a0<\/strong>yani <strong>kendini tekrarlama<\/strong> prensibine g\u00f6re kod tekrarlar\u0131ndan sak\u0131nmak gerekmektedir. <strong>Repository Patterni<\/strong> ise bize bunu sa\u011flamaktad\u0131r. Olu\u015fturdu\u011fumuz bir s\u0131n\u0131f\u00a0ile t\u00fcm tablolar\u00a0i\u00e7in <strong>CRUD<\/strong> i\u015flemlerimizi yapabilmemizi sa\u011flamaktad\u0131r ve kod tekrar\u0131n\u0131 \u00f6nlemektedir. Aksi durumda bir d\u00fc\u015f\u00fcnsenize, 30 tablolu bir yap\u0131m\u0131z mevcut ve her biri i\u00e7in <strong>CRUD<\/strong> i\u015flemleri yapmam\u0131z gerekti\u011fini? Vay anam vay&#8230;<\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/08\/RepositoryDiagram.png\"><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-394\" src=\"\/wp-content\/uploads\/2015\/08\/RepositoryDiagram.png\" alt=\"RepositoryDiagram\" width=\"566\" height=\"248\" srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/RepositoryDiagram.png 566w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/RepositoryDiagram-300x131.png 300w\" sizes=\"(max-width: 566px) 100vw, 566px\" \/><\/a><\/p>\n<h2>Unit of Work Pattern Nedir?<\/h2>\n<p>Unit of Work ise bize;<\/p>\n<blockquote><p>Veritaban\u0131 ile yap\u0131lacak olan t\u00fcm i\u015flemleri, tek bir kanal arac\u0131l\u0131\u011f\u0131 ile ger\u00e7ekle\u015ftirme ve haf\u0131zada tutma i\u015flemlerini sunmaktad\u0131r. Bu sayede i\u015flemlerin toplu halde ger\u00e7ekle\u015ftirilmesi ve hata durumunda geri al\u0131nabilmesi sa\u011flamaktad\u0131r.<\/p><\/blockquote>\n<p><strong>Unit of Work<\/strong> deseni tek ba\u015f\u0131na kullan\u0131labilece\u011fi gibi, <strong>Repository<\/strong> kurumsal tasar\u0131m deseni ile (ki makalemiz konusudur a\u015fa\u011f\u0131da beraber kullan\u0131m\u0131n\u0131 g\u00f6rece\u011fiz) veya <strong>Identity Map<\/strong> kurumsal tasar\u0131m deseni ile de kullan\u0131labilir.<\/p>\n<blockquote><p><strong>Identity Map:<\/strong> ORM geli\u015ftirirken <strong>g\u00fcncelleme (update)<\/strong> i\u015flemleri s\u0131ras\u0131nda veritaban\u0131ndan \u00e7ekilmi\u015f olan nesnenin, sadece de\u011fi\u015fime u\u011frayan alanlar\u0131n\u0131 g\u00fcncelleyebilmemizi\u00a0sa\u011flayan bir desendir.<\/p><\/blockquote>\n<p>Unit of Work deseninde ise, i\u015flemleri haf\u0131zada tutma \u00f6zelli\u011finden bahsetmi\u015ftik. <strong>Identity Map<\/strong> deseni i\u015fte\u00a0bu noktada implemente\u00a0edilebilir.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/08\/unitofwork.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-395 lazyload\" data-src=\"\/wp-content\/uploads\/2015\/08\/unitofwork.png\" alt=\"unitofwork\" width=\"635\" height=\"615\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/unitofwork.png 635w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/unitofwork-300x291.png 300w\" data-sizes=\"(max-width: 635px) 100vw, 635px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 635px; --smush-placeholder-aspect-ratio: 635\/615;\" \/><\/a><\/p>\n<p>Yukar\u0131daki \u015femay\u0131 da inceledi\u011fimizde g\u00f6rece\u011fimiz \u00fczere ilk ba\u015fta veritaban\u0131na direkt eri\u015fimi\u00a0g\u00f6r\u00fcyoruz klasik programlamada. \u0130kinci k\u0131s\u0131mda\u00a0ise bir tarafta<strong> Entity Framework<\/strong> i\u00e7in haz\u0131rlanm\u0131\u015f olan <strong>Unit of Work<\/strong> deseni ile ilgili <strong>Repository&#8217;ler <\/strong>arac\u0131l\u0131\u011f\u0131 ile veritaban\u0131na eri\u015fim var. Bu sayede <strong>Unit Test&#8217;ler<\/strong> i\u00e7in olan <strong>Mocklanm\u0131\u015f\u00a0<\/strong>s\u0131n\u0131flar arac\u0131l\u0131\u011f\u0131\u00a0ile test bir veritaban\u0131na veya in-memory haz\u0131rlanm\u0131\u015f veri alan\u0131na eri\u015fimini g\u00f6r\u00fcyoruz.<\/p>\n<blockquote><p><strong>Mock Object:<\/strong> Unit testler yaparken uygulamam\u0131z\u0131n t\u00fcm\u00fcn\u00fc ayakta tutmak\/tutabilmek zor olacakt\u0131r bir hayli. Bunun yerine uygulamam\u0131z\u0131n test ortam\u0131nda \u00e7al\u0131\u015fabilece\u011fi kadar fonksiyonlar\u0131 i\u00e7eren s\u0131n\u0131flar haz\u0131rlan\u0131r. Bu t\u00fcr s\u0131n\u0131flara <strong>Mock Object<\/strong> denir.<\/p><\/blockquote>\n<p>\u015eimdi Repository ve Unit of Work\u00a0kurumsal kal\u0131plar\u0131n\u0131n\u00a0ne oldu\u011funu anlad\u0131\u011f\u0131m\u0131za g\u00f6re, \u00f6rne\u011fimize ge\u00e7elim ve beraber kullan\u0131mlar\u0131n\u0131 detayl\u0131ca incelemeye ba\u015flayal\u0131m.<\/p>\n<p>\u00d6rne\u011fimiz gere\u011fi basitle\u015ftirilmi\u015f temel bir alt yap\u0131 tasarlayaca\u011f\u0131z. Bu alt yap\u0131m\u0131z <strong>Entity Framework<\/strong>&#8216;den yararlanarak <strong>code first<\/strong> yakla\u015f\u0131m\u0131 ile geli\u015ftirece\u011fiz ve <strong>Repository<\/strong> ve <strong>Unit of Work<\/strong> desenlerini ise maksimum seviyede izole ederek, gerek <strong>Entity Framework<\/strong>\u00a0ve\u00a0<strong>MSSQL<\/strong>\u00a0ile gereksede <strong>Mongo DB<\/strong> ilede \u00e7al\u0131\u015fabilir bir \u015fekilde mod\u00fcler geli\u015ftirmeye \u00e7al\u0131\u015faca\u011f\u0131z.<\/p>\n<p>\u00d6rne\u011fimiz basit bir <strong>Blog<\/strong> sistemi olacak ve <strong>User<\/strong>, <strong>Article<\/strong> ve <strong>Category<\/strong> s\u0131n\u0131flar\u0131ndan olu\u015facak.<\/p>\n<p>\u0130\u015fe\u00a0<strong>RepveUOW<\/strong> isminde bo\u015f bir solution olu\u015fturarak i\u00e7erisine ise\u00a0<strong>RepveUOW.Data.Model<\/strong> isminde bir s\u0131n\u0131f k\u00fct\u00fcphanesi (class library) ekleyerek ba\u015fl\u0131yorum.<\/p>\n<p>Burada isminden de anla\u015f\u0131labilece\u011fi \u00fczere <strong>Poco<\/strong> s\u0131n\u0131flar\u0131m\u0131z yani modellerimiz yer alacak. Bu sayede uygulamam\u0131z i\u00e7i bu entity nesnelerimiz <strong>orm\u00a0<\/strong>ba\u011f\u0131ms\u0131z bir \u015fekilde geli\u015fiyor olacak.<\/p>\n<p>Model katman\u0131\u00a0i\u00e7erisine ilk ba\u015fta t\u00fcm entity nesnelerimiz\u00a0i\u00e7in ortak olan <strong>CreatedDate<\/strong> \u00f6zelli\u011fini kal\u0131t\u0131m yolu ile aktarabilmek i\u00e7in\u00a0<strong>ModelBase<\/strong> isminde bir soyut s\u0131n\u0131f olu\u015fturuyoruz.<\/p>\n<pre class=\"lang:c# decode:true \">using System;\r\n\r\nnamespace RepveUOW.Data.Model\r\n{\r\n    public abstract class ModelBase\r\n    {\r\n        public DateTime CreatedDate { get; set; }\r\n    }\r\n}<\/pre>\n<p>Soyut s\u0131n\u0131f\u0131m\u0131z haz\u0131r oldu\u011funa g\u00f6re \u015fimdi entitylerimizi olu\u015fturmaya ba\u015flayabiliriz.<\/p>\n<p><strong>User<\/strong> s\u0131n\u0131f\u0131 ile ba\u015fl\u0131yoruz.<\/p>\n<pre class=\"lang:c# decode:true \">using System;\r\nusing System.Collections.Generic;\r\n\r\nnamespace RepveUOW.Data.Model\r\n{\r\n    public class User : ModelBase\r\n    {\r\n        public User()\r\n        {\r\n            this.Articles = new List&lt;Article&gt;();\r\n        }\r\n\r\n        public int Id { get; set; }\r\n        public string FirstName { get; set; }\r\n        public string LastName { get; set; }\r\n        public string Email { get; set; }\r\n        public string Password { get; set; }\r\n\r\n        \/\/ Fluently bir \u015fekilde ili\u015fkileri kullanabilmemiz i\u00e7in tan\u0131ml\u0131yoruz.\r\n        public virtual ICollection&lt;Article&gt; Articles { get; set; }\r\n    }\r\n}<\/pre>\n<p><strong>Category<\/strong> s\u0131n\u0131f\u0131 ekliyoruz.<\/p>\n<pre class=\"lang:c# decode:true \">using System.Collections.Generic;\r\n\r\nnamespace RepveUOW.Data.Model\r\n{\r\n    public class Category : ModelBase\r\n    {\r\n        public Category()\r\n        {\r\n            this.Articles = new List&lt;Article&gt;();\r\n        }\r\n\r\n        public int Id { get; set; }\r\n        public string Name { get; set; }\r\n\r\n        \/\/ Relations\r\n        public virtual ICollection&lt;Article&gt; Articles { get; set; }\r\n    }\r\n}<\/pre>\n<p>\u015eimdide <strong>Article<\/strong>\u00a0s\u0131n\u0131f\u0131n\u0131\u00a0ekliyoruz ve <strong>Model<\/strong> katman\u0131m\u0131z\u0131 tamamlam\u0131\u015f oluyoruz.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\n\r\nnamespace RepveUOW.Data.Model\r\n{\r\n    public class Article : ModelBase\r\n    {\r\n        public int Id { get; set; }\r\n        public int CategoryId { get; set; }\r\n        public int UserId { get; set; }\r\n\r\n        public string Title { get; set; }\r\n        public string Content { get; set; }\r\n\r\n        \/\/ Relations\r\n        public virtual Category Category { get; set; }\r\n        public virtual User User { get; set; }\r\n    }\r\n}<\/pre>\n<p>Modellerimizi olu\u015ftururken g\u00f6rd\u00fc\u011f\u00fcn\u00fcz\u00a0gibi\u00a0ili\u015fkileri kullanabilmek i\u00e7in altta \/\/ Relations skobunda tan\u0131mlad\u0131k. Bu ili\u015fkileri daha sonra ilgili <strong>Context<\/strong> s\u0131n\u0131f\u0131 i\u00e7erisinde context\u00a0aya\u011fa kalkarken tan\u0131mlayaca\u011f\u0131z.<\/p>\n<p>Model katman\u0131n\u0131 tasarlad\u0131\u011f\u0131m\u0131za g\u00f6re \u015fimdi <strong>Data<\/strong> katman\u0131n\u0131 olu\u015fturmaya ba\u015flayabiliriz.<strong>RepveUOW.Data\u00a0<\/strong>isminde bir s\u0131n\u0131f k\u00fct\u00fcphanesi daha olu\u015fturuyoruz ve <strong>References<\/strong> k\u0131sm\u0131nda <strong>Manage Nuget Packages<\/strong> sekmesine girip <strong>Entity Framework<\/strong>&#8216;\u00fc install ettikten sonra tekrar <strong>References<\/strong> k\u0131sm\u0131ndan <strong>Add Reference<\/strong>\u00a0se\u00e7ene\u011fini se\u00e7erek <strong>Projects<\/strong> tab\u0131ndan\u00a0<strong>RepveUOW.Data.Model<\/strong>\u00a0katman\u0131n\u0131 se\u00e7erek\u00a0referans olarak ekliyoruz.<\/p>\n<p>Referans i\u015flemlerini tamamlad\u0131\u011f\u0131m\u0131za g\u00f6re <strong>RepveUOW.Data\u00a0<\/strong>katman\u0131 i\u00e7erisinde <strong>Context<\/strong> isminde bir klas\u00f6r tan\u0131mlay\u0131p\u00a0<strong>EFBlogContext<\/strong> s\u0131n\u0131f\u0131n\u0131 olu\u015fturuyoruz.<\/p>\n<p><strong>EFBlogContext<\/strong> s\u0131n\u0131f\u0131 bizim <strong>entity framework<\/strong> i\u00e7in kullanacak oldu\u011fumuz\u00a0context&#8217;imiz olacak.<\/p>\n<pre class=\"lang:default decode:true\">using System.Data.Entity;\r\nusing RepveUOW.Data.Model;\r\n\r\nnamespace RepveUOW.Data\r\n{\r\n    public class EFBlogContext : DbContext\r\n    {\r\n        public EFBlogContext()\r\n            : base(\"BlogContext\")\r\n        {\r\n        }\r\n\r\n        public DbSet&lt;User&gt; Users { get; set; }\r\n        public DbSet&lt;Category&gt; Categories { get; set; }\r\n        public DbSet&lt;Article&gt; Articles { get; set; }\r\n\r\n        protected override void OnModelCreating(DbModelBuilder modelBuilder)\r\n        {\r\n            \/\/ \u0130li\u015fkileri kuruyoruz one-to-many olarak.\r\n            modelBuilder.Entity&lt;Article&gt;()\r\n                .HasRequired&lt;Category&gt;(x =&gt; x.Category)\r\n                .WithMany(x =&gt; x.Articles)\r\n                .HasForeignKey(x =&gt; x.CategoryId);\r\n\r\n            modelBuilder.Entity&lt;Article&gt;()\r\n                .HasRequired&lt;User&gt;(x =&gt; x.User)\r\n                .WithMany(x =&gt; x.Articles)\r\n                .HasForeignKey(x =&gt; x.UserId);\r\n\r\n            base.OnModelCreating(modelBuilder);\r\n        }\r\n    }\r\n}<\/pre>\n<p><strong>Code first<\/strong> yakla\u015f\u0131m\u0131 ile geli\u015ftirmek istedi\u011fimizden <strong>EFBlogContext<\/strong> s\u0131n\u0131f\u0131m\u0131z\u0131 <strong>System.Data.Entity<\/strong> namespace&#8217;inde bulunan <strong>DbContext<\/strong> s\u0131n\u0131f\u0131ndan t\u00fcretiyoruz. EFBlogContext&#8217;in constructor&#8217;\u0131nda DbContext s\u0131n\u0131f\u0131n\u0131n constructur&#8217;\u0131na connection string&#8217;in\u00a0ismini g\u00f6nderiyoruz. Daha sonra bu connection string ismini Data katman\u0131m\u0131z\u0131 kullanacak olan sunum katman\u0131n\u0131n ilgili App.config veya Web.config i\u00e7erisinde tan\u0131ml\u0131yor olaca\u011f\u0131z.<\/p>\n<p><strong>DbSet&#8217;ler<\/strong> arac\u0131l\u0131\u011f\u0131 ile ilgili <strong>poco<\/strong> s\u0131n\u0131flar\u0131m\u0131z\u0131 tan\u0131mlad\u0131k ve modelimiz olu\u015furken\u00a0ili\u015fkileri tan\u0131mlayabilmemiz\u00a0i\u00e7in <strong>OnModelCreating<\/strong> metotunu ezerek ilgili ili\u015fkileri tan\u0131mlad\u0131k. Fluent bir aray\u00fcze sahip oldu\u011fu i\u00e7in DbModelBuilder s\u0131n\u0131f\u0131 gayet kolay bir \u015fekilde ili\u015fkilerimizi tan\u0131mlayabildik.<\/p>\n<p>Code first olarak devam etti\u011fimiz i\u00e7in <strong>Sql Server<\/strong> \u00fczerinde hen\u00fcz hi\u00e7 bir veritaban\u0131 bulunmamaktad\u0131r. <strong>EFBlogContext<\/strong> haz\u0131r oldu\u011funa g\u00f6re \u015fimdi <strong>poco<\/strong> s\u0131n\u0131flar\u0131m\u0131zdan yola \u00e7\u0131karak kolay bir \u015fekilde veritaban\u0131 nas\u0131l olu\u015fturulur ona bir bakal\u0131m.<\/p>\n<p>Bu i\u015fleme ba\u015flamadan \u00f6nce hen\u00fcz bir sunum katman\u0131 bulunmad\u0131\u011f\u0131 i\u00e7in App.config <strong>configuration<\/strong> tag&#8217;inin i\u00e7erisinde ve <strong>configSections<\/strong> tag&#8217;inin alt\u0131nda bir conenction string tan\u0131mlayal\u0131m.<\/p>\n<pre class=\"lang:c# decode:true\">  &lt;connectionStrings&gt;\r\n    &lt;add\r\n      name=\"BlogContext\"\r\n      connectionString=\"Data Source=localhost;Initial Catalog=BlogContext;Integrated Security=True;MultipleActiveResultSets=True;\"\r\n      providerName=\"System.Data.SqlClient\" \/&gt;\r\n  &lt;\/connectionStrings&gt;<\/pre>\n<blockquote><p>\u015eimdi s\u0131ras\u0131yla View-&gt;Other Windows-&gt; <strong>Package Manager Console<\/strong> a\u00e7\u0131yoruz ve \u00fczerindeki <strong>Default project<\/strong> k\u0131sm\u0131nda\u00a0<strong>RepveUOW.Data<\/strong> se\u00e7ili oldu\u011fundan emin oluyoruz.<\/p><\/blockquote>\n<p>A\u00e7\u0131lan konsola \u00f6nce:\u00a0<strong>Enable-Migrations \u2013EnableAutomaticMigrations<\/strong>\u00a0yaz\u0131yoruz ve connection string&#8217;de herhangi bir hata yapmad\u0131 isek\u00a0<strong>Migrations<\/strong> isminde bir klas\u00f6r olu\u015fturup i\u00e7erisinde\u00a0<strong>Configuration<\/strong> s\u0131n\u0131f\u0131n\u0131 olu\u015fturdu\u011funu g\u00f6rece\u011fiz.<\/p>\n<blockquote><p>\u015eimdi tekrar Package Manager Console \u00fczerinde\u00a0<strong>Update-Database\u00a0<\/strong>yazarak veritaban\u0131n\u0131 olu\u015fturmas\u0131n\u0131 sa\u011fl\u0131yoruz.<\/p><\/blockquote>\n<p>Veritaban\u0131m\u0131z ve context&#8217;imiz olu\u015ftu\u011funa g\u00f6re \u015fimdi <strong>generic repository<\/strong> s\u0131n\u0131f\u0131n\u0131 tasarlamaya ba\u015flayabiliriz. Hemen data katman\u0131m\u0131za\u00a0<strong>Repositories<\/strong> isminde bir klas\u00f6r ekleyerek i\u00e7erisinde\u00a0<strong>IRepository<\/strong> aray\u00fcz\u00fcn\u00fc tasarlamaya ba\u015fl\u0131yoruz.<\/p>\n<p>IRepository<\/p>\n<pre class=\"lang:c# decode:true \">using System;\r\nusing System.Linq;\r\nusing System.Linq.Expressions;\r\n\r\nnamespace RepveUOW.Data.Repositories\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Model katman\u0131m\u0131zda bulunan her T tipi i\u00e7in a\u015fa\u011f\u0131da tan\u0131mlad\u0131\u011f\u0131m\u0131z fonksiyonlar\u0131 ger\u00e7ekle\u015ftirebilecek generic bir repository tan\u0131ml\u0131yoruz.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    \/\/\/ &lt;typeparam name=\"T\"&gt;&lt;\/typeparam&gt;\r\n    public interface IRepository&lt;T&gt; where T : class\r\n    {\r\n        IQueryable&lt;T&gt; GetAll();\r\n        IQueryable&lt;T&gt; GetAll(Expression&lt;Func&lt;T, bool&gt;&gt; predicate); \/\/ LINQ deste\u011fi sunabilmek i\u00e7inde expression'lar\u0131 kullan\u0131yoruz.\r\n        T GetById(int id);\r\n        T Get(Expression&lt;Func&lt;T, bool&gt;&gt; predicate);\r\n\r\n        void Add(T entity);\r\n        void Update(T entity);\r\n        void Delete(T entity);\r\n        void Delete(int id);\r\n    }\r\n}<\/pre>\n<p>\u015eimdi entity framework i\u00e7in kullan\u0131yor olaca\u011f\u0131m\u0131z <strong>EFRepository<\/strong> s\u0131n\u0131f\u0131n\u0131 ekleyerek kodlar\u0131n\u0131 a\u015fa\u011f\u0131daki gibi yaz\u0131yoruz.,<\/p>\n<pre class=\"lang:c# decode:true \">using System;\r\nusing System.Data.Entity;\r\nusing System.Data.Entity.Infrastructure;\r\nusing System.Linq;\r\nusing System.Linq.Expressions;\r\n\r\nnamespace RepveUOW.Data.Repositories\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ EntityFramework i\u00e7in haz\u0131rl\u0131yor oldu\u011fumuz bu repositoriyi daha \u00f6nceden tasarlad\u0131\u011f\u0131m\u0131z generic repositorimiz olan IRepository aray\u00fcz\u00fcn\u00fc implemente ederek tasarlad\u0131k.\r\n    \/\/\/ Bu \u015fekilde tasarlamam\u0131z\u0131n ana sebebi ise veritaban\u0131na independent(ba\u011f\u0131ms\u0131z) bir durumda kalabilmek. \u00d6rne\u011fin MongoDB i\u00e7in ise ilgili provider'\u0131 arac\u0131l\u0131\u011f\u0131 ile MongoDBRepository tasarlayabiliriz.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    \/\/\/ &lt;typeparam name=\"T\"&gt;&lt;\/typeparam&gt;\r\n    public class EFRepository&lt;T&gt; : IRepository&lt;T&gt; where T : class\r\n    {\r\n        private readonly DbContext _dbContext;\r\n        private readonly DbSet&lt;T&gt; _dbSet;\r\n\r\n        public EFRepository(EFBlogContext dbContext)\r\n        {\r\n            if (dbContext == null)\r\n                throw new ArgumentNullException(\"dbContext can not be null.\");\r\n\r\n            _dbContext = dbContext;\r\n            _dbSet = dbContext.Set&lt;T&gt;();\r\n        }\r\n\r\n        #region IRepository Members\r\n        public IQueryable&lt;T&gt; GetAll()\r\n        {\r\n            return _dbSet;\r\n        }\r\n\r\n        public IQueryable&lt;T&gt; GetAll(Expression&lt;Func&lt;T, bool&gt;&gt; predicate)\r\n        {\r\n            return _dbSet.Where(predicate);\r\n        }\r\n\r\n        public T GetById(int id)\r\n        {\r\n            return _dbSet.Find(id);\r\n        }\r\n\r\n        public T Get(Expression&lt;Func&lt;T, bool&gt;&gt; predicate)\r\n        {\r\n            return _dbSet.Where(predicate).SingleOrDefault();\r\n        }\r\n\r\n        public void Add(T entity)\r\n        {\r\n            _dbSet.Add(entity);\r\n        }\r\n\r\n        public void Update(T entity)\r\n        {\r\n            _dbSet.Attach(entity);\r\n            _dbContext.Entry(entity).State = EntityState.Modified;\r\n        }\r\n\r\n        public void Delete(T entity)\r\n        {\r\n            \/\/ E\u011fer sizlerde genelde bir kay\u0131t\u0131 silmek yerine IsDelete \u015feklinde bool bir flag alan\u0131 tutuyorsan\u0131z,\r\n            \/\/ K\u00fc\u00e7\u00fck bir refleciton kodu yard\u0131m\u0131 ile bunuda otomatikle\u015ftirebiliriz.\r\n            if (entity.GetType().GetProperty(\"IsDelete\") != null)\r\n            {\r\n                T _entity = entity;\r\n\r\n                _entity.GetType().GetProperty(\"IsDelete\").SetValue(_entity, true);\r\n\r\n                this.Update(_entity);\r\n            }\r\n            else\r\n            {\r\n                \/\/ \u00d6nce entity'nin state'ini kontrol etmeliyiz.\r\n                DbEntityEntry dbEntityEntry = _dbContext.Entry(entity);\r\n\r\n                if (dbEntityEntry.State != EntityState.Deleted)\r\n                {\r\n                    dbEntityEntry.State = EntityState.Deleted;\r\n                }\r\n                else\r\n                {\r\n                    _dbSet.Attach(entity);\r\n                    _dbSet.Remove(entity);\r\n                }\r\n            }\r\n        }\r\n\r\n        public void Delete(int id)\r\n        {\r\n            var entity = GetById(id);\r\n            if (entity == null) return;\r\n            else\r\n            {\r\n                if (entity.GetType().GetProperty(\"IsDelete\") != null)\r\n                {\r\n                    T _entity = entity;\r\n                    _entity.GetType().GetProperty(\"IsDelete\").SetValue(_entity, true);\r\n\r\n                    this.Update(_entity);\r\n                }\r\n                else\r\n                {\r\n                    Delete(entity);\r\n                }\r\n            }\r\n        }\r\n        #endregion\r\n    }\r\n}<\/pre>\n<p><strong>Repositorimiz<\/strong> haz\u0131r oldu\u011funa g\u00f6re art\u0131k Unit of Work desenini tasarlamaya ba\u015flayabiliriz.\u00a0<strong>UnitOfWork<\/strong> isminde bir klas\u00f6r daha olu\u015fturarak\u00a0i\u00e7erisinde\u00a0<strong>IUnitOfWork<\/strong> aray\u00fcz\u00fcn\u00fc tan\u0131ml\u0131yoruz.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing RepveUOW.Data.Repositories;\r\n\r\nnamespace RepveUOW.Data.UnitOfWork\r\n{\r\n    public interface IUnitOfWork : IDisposable\r\n    {\r\n        IRepository&lt;T&gt; GetRepository&lt;T&gt;() where T : class;\r\n        int SaveChanges();\r\n    }\r\n}<\/pre>\n<p>\u0130\u00e7erisinde istedi\u011fimiz tipteki repository&#8217;i bize getirecek olan <strong>GetRepository<\/strong> generic metotunu ve kaydetme i\u015flemlerini toplu yapabilmemizi sa\u011flayacak olan <strong>SaveChanges<\/strong> metotunun imzalar\u0131n\u0131\u00a0tan\u0131ml\u0131yoruz.<\/p>\n<p>\u015eimdi yine entity framework i\u00e7in kullanaca\u011f\u0131m\u0131z <strong>EFUnitOfWork<\/strong> s\u0131n\u0131f\u0131m\u0131z\u0131\u00a0<strong>UnitOfWork<\/strong> klas\u00f6r\u00fc i\u00e7erisinde tan\u0131ml\u0131yoruz.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing RepveUOW.Data.Repositories;\r\nusing System.Data.Entity;\r\n\r\nnamespace RepveUOW.Data.UnitOfWork\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ EntityFramework i\u00e7in olu\u015fturmu\u015f oldu\u011fumuz UnitOfWork.\r\n    \/\/\/ EFRepository'de oldu\u011fu gibi bu \u015fekilde tasarlamam\u0131z\u0131n ana sebebi ise veritaban\u0131na independent(ba\u011f\u0131ms\u0131z) bir durumda kalabilmek. \u00d6rne\u011fin MongoDB i\u00e7in ise ilgili provider'\u0131 arac\u0131l\u0131\u011f\u0131 ile MongoDBOfWork tasarlayabiliriz.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public class EFUnitOfWork : IUnitOfWork\r\n    {\r\n        private readonly EFBlogContext _dbContext;\r\n\r\n        public EFUnitOfWork(EFBlogContext dbContext)\r\n        {\r\n            Database.SetInitializer&lt;EFBlogContext&gt;(null);\r\n\r\n            if (dbContext == null)\r\n                throw new ArgumentNullException(\"dbContext can not be null.\");\r\n\r\n            _dbContext = dbContext;\r\n\r\n            \/\/ Buradan istedi\u011finiz gibi EntityFramework'\u00fc konfigure edebilirsiniz.\r\n            \/\/_dbContext.Configuration.LazyLoadingEnabled = false;\r\n            \/\/_dbContext.Configuration.ValidateOnSaveEnabled = false;\r\n            \/\/_dbContext.Configuration.ProxyCreationEnabled = false;\r\n        }\r\n\r\n        #region IUnitOfWork Members\r\n        public IRepository&lt;T&gt; GetRepository&lt;T&gt;() where T : class\r\n        {\r\n            return new EFRepository&lt;T&gt;(_dbContext);\r\n        }\r\n\r\n        public int SaveChanges()\r\n        {\r\n            try\r\n            {\r\n                \/\/ Transaction i\u015flemleri burada ele al\u0131nabilir veya Identity Map kurumsal tasar\u0131m kal\u0131b\u0131 kullan\u0131larak\r\n                \/\/ sadece de\u011fi\u015fen alanlar\u0131 g\u00fcncellemeyide sa\u011flayabiliriz.\r\n                return _dbContext.SaveChanges();\r\n            }\r\n            catch\r\n            {\r\n                \/\/ Burada DbEntityValidationException hatalar\u0131n\u0131 handle edebiliriz.\r\n                throw;\r\n            }\r\n        }\r\n        #endregion\r\n\r\n        #region IDisposable Members\r\n        \/\/ Burada IUnitOfWork aray\u00fcz\u00fcne implemente etti\u011fimiz IDisposable aray\u00fcz\u00fcn\u00fcn Dispose Patternini implemente ediyoruz.\r\n        private bool disposed = false;\r\n        protected virtual void Dispose(bool disposing)\r\n        {\r\n            if (!this.disposed)\r\n            {\r\n                if (disposing)\r\n                {\r\n                    _dbContext.Dispose();\r\n                }\r\n            }\r\n\r\n            this.disposed = true;\r\n        }\r\n        public void Dispose()\r\n        {\r\n            Dispose(true);\r\n            GC.SuppressFinalize(this);\r\n        }\r\n        #endregion\r\n    }\r\n}<\/pre>\n<p>Unit of Work desenide haz\u0131r oldu\u011funa g\u00f6re katmanlar\u0131n\u00a0son g\u00f6r\u00fcn\u00fcm\u00fcne bir bakal\u0131m:<\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/08\/katmanlar.jpg\"><img decoding=\"async\" class=\"size-full wp-image-397 aligncenter lazyload\" data-src=\"\/wp-content\/uploads\/2015\/08\/katmanlar.jpg\" alt=\"katmanlar\" width=\"308\" height=\"509\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/katmanlar.jpg 308w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2015\/08\/katmanlar-182x300.jpg 182w\" data-sizes=\"(max-width: 308px) 100vw, 308px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 308px; --smush-placeholder-aspect-ratio: 308\/509;\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Temel bir alt yap\u0131 tasar\u0131m\u0131m\u0131z\u0131 tamamlad\u0131\u011f\u0131m\u0131za\u00a0g\u00f6re kullan\u0131mlar\u0131na bakabilmek\u00a0ama\u00e7l\u0131\u00a0<strong>RepveUOW.Presentation.UnitTest<\/strong> isminde bir <strong>Unit Test<\/strong> projesi olu\u015ftural\u0131m.<\/p>\n<p><strong>RepveUOW.Presentation.UnitTest\u00a0<\/strong>katman\u0131n\u0131 olu\u015fturduktan sonra <strong>References<\/strong> k\u0131sm\u0131ndan <strong>Add Reference<\/strong> se\u00e7ene\u011fini se\u00e7erek, <strong>Data<\/strong> katman\u0131nda yapt\u0131\u011f\u0131m\u0131z gibi <strong>Projects<\/strong> sekmesinden <strong>Data<\/strong> ve <strong>Model<\/strong> katman\u0131m\u0131z\u0131 referans olarak ekliyoruz.<\/p>\n<p><strong>EntityTest<\/strong> isminde bir <strong>UnitTest<\/strong> s\u0131n\u0131f\u0131 olu\u015fturarak i\u00e7erisinde a\u015fa\u011f\u0131da a\u00e7\u0131klamalar\u0131 ile de g\u00f6rebildi\u011finiz gibi ilgili test\u00a0metotlar\u0131m\u0131z\u0131 tan\u0131ml\u0131yoruz.<\/p>\n<pre class=\"lang:c# decode:true \">using Microsoft.VisualStudio.TestTools.UnitTesting;\r\nusing System;\r\nusing RepveUOW.Data;\r\nusing RepveUOW.Data.UnitOfWork;\r\nusing RepveUOW.Data.Model;\r\nusing RepveUOW.Data.Repositories;\r\n\r\nnamespace RepveUOW.Presentation.UnitTest\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Repository ve UOW kullanarak ilgili test metotlar\u0131m\u0131z\u0131 yaz\u0131yoruz.\r\n    \/\/\/ &lt;\/summary&gt;\r\n    [TestClass]\r\n    public class EntityTest\r\n    {\r\n        \/\/ Entity framework i\u00e7in geli\u015ftirmi\u015f oldu\u011fumuz context. Farkl\u0131 ORM veya Veritaban\u0131 i\u00e7inde bu context'i de\u011fi\u015ftirebiliriz.\r\n        private EFBlogContext _dbContext;\r\n\r\n        private IUnitOfWork _uow;\r\n        private IRepository&lt;User&gt; _userRepository;\r\n        private IRepository&lt;Category&gt; _categoryRepository;\r\n        private IRepository&lt;Article&gt; _articleRepository;\r\n\r\n        [TestInitialize]\r\n        public void TestInitialize()\r\n        {\r\n            _dbContext = new EFBlogContext();\r\n\r\n            \/\/ EFBlogContext'i kullan\u0131yor oldu\u011fumuz i\u00e7in EFUnitOfWork'den t\u00fcreterek constructor'\u0131na\r\n            \/\/ ilgili context'i constructor injection y\u00f6ntemi ile inject ediyoruz.\r\n            _uow = new EFUnitOfWork(_dbContext);\r\n            _userRepository = new EFRepository&lt;User&gt;(_dbContext);\r\n            _categoryRepository = new EFRepository&lt;Category&gt;(_dbContext);\r\n            _articleRepository = new EFRepository&lt;Article&gt;(_dbContext);\r\n        }\r\n\r\n        [TestCleanup]\r\n        public void TestCleanup()\r\n        {\r\n            _dbContext = null;\r\n            _uow.Dispose();\r\n        }\r\n\r\n\r\n        [TestMethod]\r\n        public void AddUser()\r\n        {\r\n            User user = new User\r\n            {\r\n                FirstName = \"G\u00f6khan\",\r\n                LastName = \"G\u00f6kalp\",\r\n                CreatedDate = DateTime.Now,\r\n                Email = \"gok.gokalp@yahoo.com\",\r\n                Password = \"123456\"\r\n            };\r\n\r\n            _userRepository.Add(user);\r\n            int process = _uow.SaveChanges();\r\n\r\n            Assert.AreNotEqual(-1, process);\r\n        }\r\n\r\n        [TestMethod]\r\n        public void GetUser()\r\n        {\r\n            User user = _userRepository.GetById(1);\r\n\r\n            Assert.IsNotNull(user);\r\n        }\r\n\r\n        [TestMethod]\r\n        public void UpdateUser()\r\n        {\r\n            User user = _userRepository.GetById(1);\r\n\r\n            user.FirstName = \"Mehmet\";\r\n\r\n            _userRepository.Update(user);\r\n            int process = _uow.SaveChanges();\r\n\r\n            Assert.AreNotEqual(-1, process);\r\n        }\r\n\r\n        [TestMethod]\r\n        public void DeleteUser()\r\n        {\r\n            User user = _userRepository.GetById(1);\r\n\r\n            _userRepository.Delete(user);\r\n            int process = _uow.SaveChanges();\r\n\r\n            Assert.AreNotEqual(-1, process);\r\n        }\r\n    }\r\n}<\/pre>\n<blockquote><p><strong>Not:<\/strong> Test metotlar\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rmadan \u00f6nce <strong>App.config<\/strong> i\u00e7erisinde <strong>configSections<\/strong> tag&#8217;inin alt\u0131na tekrardan ilgili connection string&#8217;i eklemeyi unutmuyoruz.<\/p><\/blockquote>\n<p>Bu makalemizde temel bir \u015fekilde kurumsal d\u00fczeyde alt yap\u0131 tasarlarken <strong>Generic Repository<\/strong> ve <strong>Unit of Work<\/strong> desenlerinin uygulan\u0131\u015f\u0131n\u0131 g\u00f6rm\u00fc\u015f olduk.<\/p>\n<p>\u0130lgili proje \u00f6rne\u011fini a\u015fa\u011f\u0131dan indirebilirsiniz.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2015\/08\/RepveUOW.rar\">RepveUOW<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Merhaba arkada\u015flar, bu makalemde sizlerle Generic\u00a0Repository ve Unit of Work\u00a0kurumsal tasar\u0131m kal\u0131plar\u0131n\u0131\u00a0uygulayarak temel bir alt yap\u0131 (infrastructure) tasarlayaca\u011f\u0131z. Tasarlama s\u0131ras\u0131nda Entity Framework&#8217;den yararlanarak code first\u00a0yakla\u015f\u0131m\u0131 ile geli\u015ftirece\u011fiz. Tabi ki alt yap\u0131m\u0131z ORM ba\u011f\u0131ms\u0131z (independent) olacak. Alt yap\u0131m\u0131z\u0131 geli\u015ftirirken\u00a0makul bir seviyede s\u0131k\u0131 s\u0131k\u0131ya ba\u011fl\u0131 (tight coupled) olmadan \u00a0gev\u015fek ba\u011flanm\u0131\u015f (loosely coupled) bir \u015fekilde geli\u015ftirmeye \u00e7al\u0131\u015faca\u011f\u0131z ki, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[68,98],"tags":[103,102,105,99,101,100,104],"class_list":["post-391","post","type-post","status-publish","format-standard","hentry","category-architectural","category-kurumsal-tasarim-kaliplari-enterprise-design-patterns","tag-entity-framework-code-first","tag-infrastructure","tag-mock-nedir","tag-repository-pattern","tag-repository-ve-unit-of-work","tag-unit-of-work-pattern","tag-unit-test"],"translation":{"provider":"WPGlobus","version":"3.0.6","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":false,"content":false,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2015-08-05T22:06:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-08-05T22:06:41+00:00\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak\",\"datePublished\":\"2015-08-05T22:06:15+00:00\",\"dateModified\":\"2015-08-05T22:06:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/\"},\"wordCount\":1606,\"commentCount\":67,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"keywords\":[\"Entity Framework Code First\",\"Infrastructure\",\"Mock Nedir\",\"Repository Pattern\",\"Repository ve Unit of Work\",\"Unit of Work Pattern\",\"Unit Test\"],\"articleSection\":[\"Architectural\",\"Kurumsal Tasar\u0131m Kal\u0131plar\u0131 (Enterprise Design Patterns)\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/\",\"name\":\"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"datePublished\":\"2015-08-05T22:06:15+00:00\",\"dateModified\":\"2015-08-05T22:06:41+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/","og_locale":"tr_TR","og_type":"article","og_title":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2015-08-05T22:06:15+00:00","article_modified_time":"2015-08-05T22:06:41+00:00","author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"14 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak","datePublished":"2015-08-05T22:06:15+00:00","dateModified":"2015-08-05T22:06:41+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/"},"wordCount":1606,"commentCount":67,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"keywords":["Entity Framework Code First","Infrastructure","Mock Nedir","Repository Pattern","Repository ve Unit of Work","Unit of Work Pattern","Unit Test"],"articleSection":["Architectural","Kurumsal Tasar\u0131m Kal\u0131plar\u0131 (Enterprise Design Patterns)"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/","url":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/","name":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"datePublished":"2015-08-05T22:06:15+00:00","dateModified":"2015-08-05T22:06:41+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1794317391"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=391"}],"version-history":[{"count":9,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/391\/revisions"}],"predecessor-version":[{"id":404,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/391\/revisions\/404"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}