Bu yazımda .Net Core MVC projemize .Net EF Core paketini ekledikten sonra CRUD işlemlerimiz için generic bir yapı oluşturacağız bu sayede DB 'deki her Entitiy' miz için bir CRUD sınıfı oluşturup tekrarlı kod yazmak yerine bahsedeceğimiz bu generic repository' i kullanacağız.
Okurken ne dinlemeli ?
İlk olarak bu yazımda bahsettiğim gibi bir .Net Core MVC projesi oluşturalım ve Data adında bir klasör ekleyerek başlayalım. Entity FrameworkCore nuget paketimizi Package Manager Console' dan aşağıdaki gibi ekleyelim.
Install-Package Microsoft.EntityFrameworkCore
Şimdi DBContext'i yazalım bundan önce örnek projemize Person Entity' sini ekleyelim.
public class Person :IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName
{ get; set; }
}
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options)
: base(options)
{
}
public DbSet<Person> Persons { get; set; }
protected override void
OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
Kullanacağımız Entitiy'leri IEntity arayüzünü miras aldırarak her modelin Id property'si olmaya zorladık. Bunu tercih etmeyebilirsiniz. Tercih sizin.
public interface IEntity
{
int Id { get; set; }
}
Oluşturduğumuz DBContext' i Stratup.cs sınıfında ConfigureServices metoduna ekleyelim.
services.AddDbContext<DataContext>(options
=>options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
Veri tabanı bağlantısını belirlemek için ise appsettings.json doyasına ilgili Connection String' i yazalım.
,
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=GenericRepository;Trusted_Connection=True;MultipleActiveResultSets=true"
}
Ben local veritabanını kullanıyorum ve GenericRepository isminde bir DB'ye bağlanmak istediğimi söylüyorum. Bu bilgileri kendi ihtiyaçlarınıza göre düzenleyebilirsiniz. Eğer Local SQL Server' da GenericRepository adında DB' niz yok ise hata almamak için oluşturun.
Şimdi gelelim DB migrations'a oluşturudğumuz Entitiy'e göre Person adında bir tablomuz olması gerek. Package Manager Console' da aşağıdaki komutları sırası ile çalıştıralım:
PM>
add-migration MyFirstMigration
PM>
Update-Database
Tablomuz oluştu ve projemize Migrations adında bir klasör eklendi.Gelelim Generic Repository' mizi oluşturmaya.
public interface IGenericRepository<TEntity> where TEntity
: class, IEntity
{
IQueryable<TEntity> GetAll();
Task<TEntity> GetById(int id);
Task Create(TEntity entity);
Task Update(int id, TEntity entity);
Task Delete(int id);
}
Interface'miz görüldüğü gibi temel CRUD işlemlerinden oluşmakta ve IEntity arayüzü ile kısıtlanmakta.
public class GenericRepository<TEntity> :
IGenericRepository<TEntity> where TEntity : class, IEntity
{
private readonly DataContext _dbContext;
public GenericRepository(DataContext dbContext)
{
_dbContext = dbContext;
}
public IQueryable<TEntity> GetAll()
{
return _dbContext.Set<TEntity>().AsNoTracking();
}
public async
Task<TEntity> GetById(int id)
{
return await
_dbContext.Set<TEntity>()
.AsNoTracking()
.FirstOrDefaultAsync(e
=> e.Id == id);
}
public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> where)
{
return _dbContext.Set<TEntity>().AsNoTracking().Where(where);
}
public async Task
Create(TEntity entity)
{
await _dbContext.Set<TEntity>().AddAsync(entity);
await _dbContext.SaveChangesAsync();
}
public async Task
Update(int id, TEntity entity)
{
_dbContext.Set<TEntity>().Update(entity);
await _dbContext.SaveChangesAsync();
}
public async Task
Delete(int id)
{
var entity = await GetById(id);
_dbContext.Set<TEntity>().Remove(entity);
await _dbContext.SaveChangesAsync();
}
}
CRUD işlemlerimizde async kullandığımız için bu CRUD işlemlerini kullanacak repository'lerin metodlarının önüne Task Keyword'ünü eklememiz gerekecek. IQueryable kullandığımız yerlerde unit of work 'u gözetebilmek için AsNoTracking() kullandık. AsNoTracking sorgunun daha hızlı getirmesini sağlar ve çağrımı yapılan IQueryable collection 'da herhangi bir güncelleme olmadığını garantiler. EF 6 DBSet ile gelen yeni özellikler olan IQueryable ve IEnumerable konularını buradan inceleyebilirsiniz.
Person Repository'sini kodlayalım.
public interface IPersonRepository: IGenericRepository<Person>
{
Task<Person> GetCoolestPerson();
}
public class PersonRepository :
GenericRepository<Person>, IPersonRepository
{
public PersonRepository(DataContext dbContext)
: base(dbContext)
{
}
public async
Task<Person> GetCoolestPerson()
{
return await GetAll()
.OrderByDescending(c =>
c.Name)
.FirstOrDefaultAsync();
}
}
Ve PersonRespository'i ConfigureService'de DI containere ekleyelim böylece controller'ımıza Dependency Injection yapabileceğiz.
public class HomeController : Controller
{
//public
IActionResult Index()
//{
// return View();
//}
private readonly IPersonRepository _repository;
public HomeController(IPersonRepository repository)
{
_repository = repository;
}
public async
Task<IActionResult> Index()
{
var category = new Person
{
Name = "Sema",
LastName = "KUDU"
};
await _repository.Create(category);
var coolestCategory = await _repository.GetCoolestPerson();
ViewBag.CoolestName =
coolestCategory.Name;
ViewBag.CoolestLastName =
coolestCategory.LastName;
return View();
}
public IActionResult Privacy()
{
return View();
}
...
Projemizi çalıştıralım.
DB ye ilgili kaydın eklendiğini görelim.
Async Programlamadan kısaca bahsedecek olursak: Paralel bir programlama tekniğidir. İstekler sonucu açılacak olan thread'ler ana thread'den bağımsız olarak çalışıp kendi işini yapıp cevabı ana thread'e döner böylece ana thread bloklanmamış olur. Binlerce istek olabileceğini düşünürsek uygulamamızın performansını (Performance Bottlenecks) ve cevap verebilirliliğini (Responsiveness) artırmış oluruz.Detaylı bilgi için bu yazıyı okuyabilirsiniz.
Kaynaklar:
https://codingblast.com/entity-framework-core-generic-repository/
https://code-maze.com/async-generic-repository-pattern/
Ve her zamanki gibi projenin tam hali burada.
Hoşça kalın.
Hiç yorum yok:
Yorum Gönder