Skip to content

Instantly share code, notes, and snippets.

@christianhelle
Created June 13, 2018 11:46
Show Gist options
  • Save christianhelle/4098f7e04246637d25117115eba6ce39 to your computer and use it in GitHub Desktop.
Save christianhelle/4098f7e04246637d25117115eba6ce39 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Threading.Tasks;
namespace ChristianHelle.Toolbox.Data.Repositories
{
public interface IDatabaseContextFactory
{
DbContext Create(string nameOrConnectionString);
}
public interface IRepository<T>
{
IDatabaseContextFactory ContextFactory { get; }
string NameOrConnectionString { get; set; }
Task<IEnumerable<T>> GetAllAsync(bool orderByDesc = false, params string[] includeProperties);
Task<IEnumerable<T>> GetAsync(int page = 0, int count = int.MaxValue, bool orderByDesc = false, params string[] includeProperties);
Task<T> FindAsync(int id, params string[] includeProperties);
Task<bool> ExistsAsync(T entity);
Task<T> CreateAsync();
Task<T> CreateAsync(T entity);
T Create(T entity);
Task<IEnumerable<T>> CreateAsync(IEnumerable<T> entity);
Task<T> RefreshAsync(T entity);
Task<T> UpdateAsync(T entity);
Task<IEnumerable<T>> UpdateAsync(IEnumerable<T> entities);
Task DeleteAsync(int id);
Task DeleteAsync(T entity);
Task DeleteAsync(IEnumerable<T> entities);
}
public interface IIdentifiableType
{
int Id { get;set; }
}
public interface IModifiableItem
{
DateTime? LastModifiedDate { get; set; }
}
public class Repository<T> : IRepository<T> where T : class, IIdentifiableType
{
public Repository(IDatabaseContextFactory contextFactory, string nameOrConnectionString = null)
{
ContextFactory = contextFactory;
NameOrConnectionString = nameOrConnectionString;
}
public IDatabaseContextFactory ContextFactory { get; }
public string NameOrConnectionString { get; set; }
public virtual async Task<IEnumerable<T>> GetAllAsync(bool orderByDesc = false, params string[] includeProperties)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
IQueryable<T> set = context.Set<T>();
set = orderByDesc ? set.OrderByDescending(c => c.Id) : set.OrderBy(c => c.Id);
set = includeProperties.Aggregate(set, (current, property) => current.Include(property));
return await set.ToListAsync();
}
}
public virtual async Task<IEnumerable<T>> GetAsync(int page = 0, int count = 2147483647, bool orderByDesc = false, params string[] includeProperties)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
IQueryable<T> set = context.Set<T>();
set = orderByDesc ? set.OrderByDescending(c => c.Id) : set.OrderBy(c => c.Id);
set = includeProperties.Aggregate(set, (current, property) => current.Include(property));
return await set.Skip(page*count)
.Take(count)
.ToListAsync();
}
}
public virtual async Task<T> FindAsync(int id, params string[] includeProperties)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
IQueryable<T> set = context.Set<T>();
set = includeProperties.Aggregate(set, (current, property) => current?.Include(property));
return await (set?.FirstOrDefaultAsync(c => c.Id == id) ?? Task.FromResult<T>(null));
}
}
public virtual async Task<bool> ExistsAsync(T entity)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
return await (context.Set<T>()?.FindAsync(entity?.Id) ?? Task.FromResult<T>(null)) != null;
}
public virtual Task<T> CreateAsync() => CreateAsync(Activator.CreateInstance<T>());
public virtual async Task<T> CreateAsync(T entity)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
context.Set<T>()?.Add(entity);
await context.SaveChangesAsync();
}
return entity;
}
public T Create(T entity)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
context.Set<T>()?.Add(entity);
context.SaveChanges();
}
return entity;
}
public virtual async Task<IEnumerable<T>> CreateAsync(IEnumerable<T> entities)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
context.Set<T>()?.AddRange(entities);
await context.SaveChangesAsync();
}
return entities;
}
public virtual async Task<T> RefreshAsync(T entity)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
return await (context.Set<T>()?.FindAsync(entity?.Id) ?? Task.FromResult<T>(null));
}
public virtual async Task<T> UpdateAsync(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
if (entity.Id == 0)
throw new ArgumentException("Id must not be 0 otherwise this method will create a insert a new record");
using (var context = ContextFactory.Create(NameOrConnectionString))
{
TryUpdateLastModifiedDate(entity);
context.Set<T>()?.AddOrUpdate(t => t.Id, entity);
await context.SaveChangesAsync();
}
return entity;
}
public virtual async Task<IEnumerable<T>> UpdateAsync(IEnumerable<T> entities)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
foreach (var entity in entities)
{
TryUpdateLastModifiedDate(entity);
context.Set<T>()?.Attach(entity);
}
await context.SaveChangesAsync();
}
return entities;
}
private static void TryUpdateLastModifiedDate(T entity)
{
var modifiableItem = entity as IModifiableItem;
if (modifiableItem != null)
modifiableItem.LastModifiedDate = DateTime.UtcNow;
}
public virtual async Task DeleteAsync(int id)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
var entity = await (context.Set<T>()?.FindAsync(id) ?? Task.FromResult<T>(null));
context.Set<T>()?.Remove(entity);
await context.SaveChangesAsync();
}
}
public virtual async Task DeleteAsync(T entity)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
context.Set<T>()?.Attach(entity);
context.Set<T>()?.Remove(entity);
await context.SaveChangesAsync();
}
}
public virtual async Task DeleteAsync(IEnumerable<T> entities)
{
using (var context = ContextFactory.Create(NameOrConnectionString))
{
var list = entities.ToList();
foreach (var entity in list)
context.Set<T>()?.Attach(entity);
context.Set<T>()?.RemoveRange(list);
await context.SaveChangesAsync();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment