{"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 decoding=\"async\" class=\"aligncenter size-full wp-image-394 lazyload\" data-src=\"\/wp-content\/uploads\/2015\/08\/RepositoryDiagram.png\" alt=\"RepositoryDiagram\" width=\"566\" height=\"248\" data-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\" data-sizes=\"(max-width: 566px) 100vw, 566px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 566px; --smush-placeholder-aspect-ratio: 566\/248;\" \/><\/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)&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/generic-repository-ve-unit-of-work-kullanarak-basic-infrastructure-tasarlamak\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">Generic Repository ve Unit of Work Kullanarak Temel Bir Infrastructure Tasarlamak<\/span><\/a><\/div>\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","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","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 v27.3 - 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=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"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=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"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}]}}