# Generic Repository Pattern

**Generic Repository Pattern**

Merhaba arkadaşlar, bu yazıda sizlere Generic Repository Pattern kavramından bahsecedeğim.

**Repository Pattern Nedir?**

* Veriye erişim ve yönetimi kapsamında, tek bir noktadan yönetilebilen yapılara Repository Pattern diyoruz.
* Repository Pattern kullanmak, projelerimizin rahat ve kolay ölçeklenebilmesini, büyüyebilmesini sağlar.
* Repository Patternin kullanılmadığı durumlarda, yazılan kodlar tekrara girme eğilimine girer ve kod spaghetti (baştan aşağıya karışık) yapıya doğru gider. Yönetilemez hale gelir.

**Generic Repository Pattern Nedir?**

* Generic, "tipi değişen" demektir.
* Generic repository pattern dediğimizde, repositorymizin içerisindeki kullanılan Tip nesnesinin değişebileceğini anlarız. Yani, merkezi bir repository yapımız var iken, bu merkezi repository desenimiz, t\_Users tipi alabileceği gibi t\_Customers tipi de alabilir olduğunu anlarız.
* Bu tarz generic yapılar, mimari anlamda projeye büyük kolaylıklar sağlar.
* Generic yapılar, mimari kodlamada olmazsa olmazlardandır, hayal gücü ile doğru orantılı olarak genişlemeye müsaiddir.

**Senaryo MSSQL Tablo Yapısı**

![](https://dev.arksoft.com.tr/wp-content/uploads/2022/06/061122_1519_GenericRepo1.png)

* PhoneBookDB veritabanı oluşturdum
* t\_Users tablosu oluşturdum
* Amacımız, bu DBye, Generic Repository Pattern yaklaşımı ile ulaşmak olacak.

**Program** ![](https://dev.arksoft.com.tr/wp-content/uploads/2022/06/061122_1519_GenericRepo2.png)

**PhoneBookDBContext.cs**

using GenericRepositoryArge.Base;

using Microsoft.EntityFrameworkCore;

namespace GenericRepositoryArge.Context

{

// dbContextimiz public class PhoneBookDbContext : DbContext

{

// constructorumuz public PhoneBookDbContext(DbContextOptions\<PhoneBookDbContext> options) : base(options)

{

}

// tablolarımız public DbSet\<t\_Users> t\_Users { get; set; }

}

}

**IEntityBase.cs**

using GenericRepositoryArge.Context;

using Microsoft.EntityFrameworkCore;

using System;

using System.ComponentModel.DataAnnotations;

using System.Linq;

using System.Threading.Tasks;

namespace GenericRepositoryArge.Base

{

// base interfaceimiz public interface IEntityBase

{

// buraya ihtiyacımıza göre eklemeler yapabiliriz

}

// generic classımız public class EntityBase\<TKey> : IEntityBase

{

// primary key kolonumuz, türü generic

\[Key]

public TKey Id { get; set; } // tüm tablolarda ortak olan kolonlar public DateTime CreatedAt { get; set; } // .. varsa diğerleri

}

// t\_users tablomuz, primary key türü integer public class t\_Users : EntityBase\<int>

{

// tablo kolonlarımız public string UserName { get; set; } // .. varsa diğer kolonlar

}

// generic interfaceimiz, tablo ve primarykey türü alır, baseEntityden türemek zorundadır // tüm tablolar bu interface üzerinden türeyebilir public interface IRepositoryBase\<TEntity, TKey> where TEntity : EntityBase\<TKey>

{

// tüm kayıtları döndürecek olan methodumuz, expression filter parametre destekli, IQueryable döndürüyoruz

IQueryable\<TEntity> GetAll(Func\<TEntity, bool> filter = null);

// Idye göre kayıt getir (primary key türü generic)

Task\<TEntity> GetById(TKey id);

// tabloya insert eden method

Task\<TEntity> Insert(TEntity entity);

// satırı update eden method

Task\<TEntity> Update(TEntity entity);

// tablodan veri silen method

Task\<TEntity> Delete(TEntity entity);

// .. varsa diğer methodlar

}

// repository classımız public class RepositoryBase\<TEntity, TKey> : IRepositoryBase\<TEntity, TKey> where TEntity : EntityBase\<TKey>

{

// dbContext nesnemiz, bu repository bu context ile muhatap olacak private readonly DbContext context; // constructor public RepositoryBase(DbContext context)

{

this.context = context;

}

// generic delete methodumuz, virtual yapmamın sebebi ezilebilir olmasını istememdir public virtual Task\<TEntity> Delete(TEntity entity)

{

context.Set\<TEntity>().Remove(entity);

context.SaveChanges();

return Task.FromResult(entity);

}

// generic GetAll methodumuz, virtual yapmamın sebebi ezilebilir olmasını istememdir public virtual IQueryable\<TEntity> GetAll(Func\<TEntity, bool> filter = null)

{

// performanslı getirsin diye AsNoTracking kullanıldı return (filter == null) ? context.Set\<TEntity>().AsNoTracking() : context.Set\<TEntity>().AsNoTracking().Where(filter).AsQueryable();

}

// generic getById methodumuz, virtual yapmamın sebebi ezilebilir olmasını istememdir public virtual Task\<TEntity> GetById(TKey id)

{

return Task.FromResult(context.Set\<TEntity>().AsNoTracking().FirstOrDefault(x => x.Id.Equals(id)));

}

// generic insert methodumuz, virtual yapmamın sebebi ezilebilir olmasını istememdir public virtual async Task\<TEntity> Insert(TEntity entity)

{

await context.Set\<TEntity>().AddAsync(entity); await context.SaveChangesAsync(); return entity;

}

// generic update methodumuz, virtual yapmamın sebebi ezilebilir olmasını istememdir public virtual async Task\<TEntity> Update(TEntity entity)

{

context.Set\<TEntity>().Update(entity);

await context.SaveChangesAsync(); return entity;

}

}

// t\_Users tablosuna ilişkin arayüz repositorymiz. Tüm repositoryler bundan türetilir. public interface IUserRepository : IRepositoryBase\<t\_Users, int>

{

}

// t\_Users repositorymiz. Primary key tipi integer, tablomuz t\_users anlamındadır. public class UserRepository : RepositoryBase\<t\_Users, int>, IUserRepository

{

// constructorumuz public UserRepository(PhoneBookDbContext context) : base(context)

{

// bu repository tanımlanırken buraya context parametre geçilir, bu context bu repository için muhatap olur.

}

}

}

**Program.cs**

using GenericRepositoryArge.Base;

using GenericRepositoryArge.Context;

using Microsoft.EntityFrameworkCore;

using Microsoft.Extensions.DependencyInjection;

using System;

namespace GenericRepositoryArge

{

class Program

{

static void Main(string\[] args)

{

Test();

Console.WriteLine("ok");

Console.ReadLine();

}

private async static void Test()

{

string conStr = @"Data Source=DESKTOP-PBV06FI\Server2014; Initial Catalog=PhoneBookDB; Persist Security Info=True; Integrated Security=SSPI;pooling=true;"; // dependency injection setupumuz // SQL server kullanacağımızı söylüyoruz, PhoneBookDbContext'i kullanacağız, // interface'e karşılık hangi Repositorynin ayağa kalkacağını belirliyoruz var serviceProvider = new ServiceCollection()

.AddDbContext\<PhoneBookDbContext>(x => x.UseSqlServer(conStr))

.AddScoped\<IUserRepository, UserRepository>()

.BuildServiceProvider();

// userRepository oluştur var userRepo = serviceProvider.GetService\<IUserRepository>(); // entity oluştur

t\_Users entity = new t\_Users() { UserName = "Hüsamettin4", CreatedAt = DateTime.Now };

Console.WriteLine("Kayıt eklendi");

// kaydet var res2 = await userRepo.Insert(entity); // verileri getir var res = await userRepo.GetAll().ToListAsync(); // verileri yaz foreach (var item in res)

{

Console.WriteLine($"{item.Id} {item.UserName} {item.CreatedAt}");

}

}

}

}

**Sonuç**

* Bu dokumanda Generic Repository Pattern yapısını uygulamalı görmüş olduk
* Dependency Injection kavramını kullanmış olduk
* Her tablo için Repository oluşturulabilir, tüm repositoryler merkezi yerden beslenir (Generic Repository Pattern)
* Bu yapı, her türlü projede mimari olarak kullanılabilir, ölçeklenebilir, genişletilebilir.
  * MSSQL ve POSTGRE providerlari ile çalışılabilir
  * ORACLE entegrasyonu yapılabilir (İlave kodlamalar ile)
  * Ado.Net mimarisi entegre edilebilir
  * Dapper mimarisi entegre edilebilir

Saygılarımla,

Hüsamettin ELALMIŞ – 11.06.2022

<husamettin.elalmis@arksoft.com.tr>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.yazilimciyiz.biz/haziran-2022/generic-repository-pattern.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
