Commit 242399b9 authored by boncho vylkov's avatar boncho vylkov

Create new branch with generic repository pattern

parent 74fa5ad5
namespace MvcCoreTemplate.Data.Common.Repositories
{
using System.Linq;
using MvcCoreTemplate.Data.Common.Models;
public interface IDeletableEntityRepository<TEntity> : IRepository<TEntity>
where TEntity : class, IDeletableEntity
{
IQueryable<TEntity> AllWithDeleted();
void HardDelete(TEntity entity);
void Undelete(TEntity entity);
}
}
namespace MvcCoreTemplate.Data.Common.Repositories
{
using System;
using System.Linq;
using System.Threading.Tasks;
public interface IRepository<TEntity> : IDisposable
where TEntity : class
{
IQueryable<TEntity> All();
Task<TEntity> GetByIdAsync(params object[] id);
void Add(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
Task<int> SaveChangesAsync();
}
}
namespace MvcCoreTemplate.Data.Repositories
{
using System;
using System.Linq;
using MvcCoreTemplate.Data.Common.Models;
using MvcCoreTemplate.Data.Common.Repositories;
public class EfDeletableEntityRepository<TEntity> : EfRepository<TEntity>, IDeletableEntityRepository<TEntity>
where TEntity : class, IDeletableEntity
{
public EfDeletableEntityRepository(ApplicationDbContext context)
: base(context)
{
}
public override IQueryable<TEntity> All() => base.All().Where(x => !x.IsDeleted);
public IQueryable<TEntity> AllWithDeleted() => base.All();
public void HardDelete(TEntity entity)
{
base.Delete(entity);
}
public void Undelete(TEntity entity)
{
entity.IsDeleted = false;
entity.DeletedOn = null;
this.Update(entity);
}
public override void Delete(TEntity entity)
{
entity.IsDeleted = true;
entity.DeletedOn = DateTime.UtcNow;
this.Update(entity);
}
}
}
namespace MvcCoreTemplate.Data.Repositories
{
using System;
using System.Linq;
using System.Threading.Tasks;
using MvcCoreTemplate.Data.Common.Repositories;
using Microsoft.EntityFrameworkCore;
public class EfRepository<TEntity> : IRepository<TEntity>
where TEntity : class
{
public EfRepository(ApplicationDbContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
this.Context = context;
this.DbSet = this.Context.Set<TEntity>();
}
protected DbSet<TEntity> DbSet { get; set; }
protected ApplicationDbContext Context { get; set; }
public virtual IQueryable<TEntity> All() => this.DbSet.AsQueryable();
public Task<TEntity> GetByIdAsync(params object[] id) => this.DbSet.FindAsync(id);
public virtual void Add(TEntity entity)
{
var entry = this.Context.Entry(entity);
if (entry.State != EntityState.Detached)
{
entry.State = EntityState.Added;
}
else
{
this.DbSet.Add(entity);
}
}
public virtual void Update(TEntity entity)
{
var entry = this.Context.Entry(entity);
if (entry.State == EntityState.Detached)
{
this.DbSet.Attach(entity);
}
entry.State = EntityState.Modified;
}
public virtual void Delete(TEntity entity)
{
var entry = this.Context.Entry(entity);
if (entry.State != EntityState.Deleted)
{
entry.State = EntityState.Deleted;
}
else
{
this.DbSet.Attach(entity);
this.DbSet.Remove(entity);
}
}
public Task<int> SaveChangesAsync() => this.Context.SaveChangesAsync();
public void Dispose() => this.Context.Dispose();
}
}
using System;
using MvcCoreTemplate.Data.Common.Repositories;
using MvcCoreTemplate.Data.Models;
using MvcCoreTemplate.Web.Infrastructure.Models.Features;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using AutoMapper.QueryableExtensions;
namespace MvcCoreTemplate.Services.Data
{
public class CommonService : ICommonService
{
private readonly IDeletableEntityRepository<Feature> repository;
public CommonService(IDeletableEntityRepository<Feature> repository)
{
this.repository = repository;
}
public string TestService()
{
return "TestService";
}
public IEnumerable<FeatureViewModel> CreateFeatures()
{
List<Feature> allFeatures = new List<Feature>();
Feature automapper = new Feature()
{
Name = "Automapper",
Description = "Maps object properties by name and type. Additional configuration applied",
};
Feature dbExtend = new Feature()
{
Name = "Extend on each db model",
Description = "Each db model has additional properties, which are handled automatically",
};
Feature repository = new Feature()
{
Name = "Repository pattern",
Description = "Implementation of Generic Repository pattern",
};
allFeatures.Add(automapper);
allFeatures.Add(dbExtend);
allFeatures.Add(repository);
this.repository.Add(automapper);
this.repository.Add(dbExtend);
this.repository.Add(repository);
this.repository.SaveChangesAsync().GetAwaiter().GetResult();
return allFeatures.AsQueryable().ProjectTo<FeatureViewModel>().ToList();
}
}
}
using System;
using MvcCoreTemplate.Data.Models;
using MvcCoreTemplate.Web.Infrastructure.Models.Features;
using System;
using System.Collections.Generic;
using System.Text;
......@@ -7,5 +9,6 @@ namespace MvcCoreTemplate.Services.Data
public interface ICommonService
{
string TestService();
IEnumerable<FeatureViewModel> CreateFeatures();
}
}
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MvcCoreTemplate.Data.Models\MvcCoreTemplate.Data.Models.csproj" />
<ProjectReference Include="..\MvcCoreTemplate.Web.Infrastructure\MvcCoreTemplate.Web.Infrastructure.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
using System;
namespace MvcCoreTemplate.Web.Infrastructure.Models.Base
{
public class BaseViewModel<TKey>
{
public TKey Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public bool IsDeleted { get; set; }
public DateTime? DeletedOn { get; set; }
}
}
using MvcCoreTemplate.Data.Models;
using MvcCoreTemplate.Web.Infrastructure.Mapping;
using MvcCoreTemplate.Web.Infrastructure.Models.Base;
namespace MvcCoreTemplate.Web.Infrastructure.Models.Features
{
public class FeatureViewModel : BaseViewModel<int>, IMapFrom<Feature>
{
public string Name { get; set; }
public string Description { get; set; }
}
}
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
......@@ -8,4 +8,8 @@
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MvcCoreTemplate.Data.Models\MvcCoreTemplate.Data.Models.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MvcCoreTemplate.Services.Data;
using MvcCoreTemplate.Data.Common.Repositories;
using MvcCoreTemplate.Data.Models;
using AutoMapper.QueryableExtensions;
using MvcCoreTemplate.Web.Infrastructure.Models.Features;
namespace MvcCoreTemplate.Web.Controllers
{
public class FeaturesController : BaseController
{
private readonly IDeletableEntityRepository<Feature> repository;
public FeaturesController(IDeletableEntityRepository<Feature> repository,ICommonService commonService) : base(commonService)
{
this.repository = repository;
}
public IActionResult Index()
{
var allFeatures = this.repository.All().ProjectTo<FeatureViewModel>().ToList();
if (allFeatures.Count==0)
{
allFeatures.AddRange(commonService.CreateFeatures());
}
return View(allFeatures);
}
}
}
\ No newline at end of file
......@@ -15,8 +15,8 @@ namespace MvcCoreTemplate.Web.Controllers
public IActionResult Index()
{
var model = this.commonService.TestService();
return View("Index",model);
return View();
}
public IActionResult About()
......
......@@ -49,6 +49,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Data\" />
<Folder Include="Views\Features\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MvcCoreTemplate.Common\MvcCoreTemplate.Common.csproj" />
......
......@@ -13,7 +13,9 @@ using MvcCoreTemplate.Web.Infrastructure.Mapping;
using MvcCoreTemplate.Web.Models.AccountViewModels;
using System.Reflection;
using MvcCoreTemplate.Data.Seeding;
using MvcCoreTemplate.Data.Common.Repositories;
using MvcCoreTemplate.Data.Repositories;
using MvcCoreTemplate.Web.Infrastructure.Models.Features;
namespace MvcCoreTemplate.Web
{
......@@ -58,6 +60,10 @@ namespace MvcCoreTemplate.Web
services.AddMvc();
// Data
services.AddScoped(typeof(IDeletableEntityRepository<>), typeof(EfDeletableEntityRepository<>));
services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
......@@ -69,8 +75,8 @@ namespace MvcCoreTemplate.Web
{
AutoMapperConfig.RegisterMappings(
typeof(LoginViewModel).GetTypeInfo().Assembly,
typeof(LoginViewModel).GetTypeInfo().Assembly);
typeof(FeatureViewModel).GetTypeInfo().Assembly,
typeof(FeatureViewModel).GetTypeInfo().Assembly);
......
@model List<MvcCoreTemplate.Web.Infrastructure.Models.Features.FeatureViewModel>
@{
ViewData["Title"] = "Index";
}
<h2>Features</h2>
<div class="row">
@for (int i = 0; i < Model.Count; i++)
{
<div class="col-md-3">
<h2>@Model[i].Name</h2>
<p>@Model[i].Description</p>
</div>
}
</div>
@model string
@{
@{
ViewData["Title"] = "Home Page";
}
......@@ -20,7 +19,6 @@
Learn More
</a>
</p>
<p>@Model</p>
</div>
</div>
<div class="item">
......@@ -66,6 +64,7 @@
<span class="sr-only">Next</span>
</a>
</div>
<h3>Features</h3>
<div class="row">
<div class="col-md-3">
......
......@@ -33,8 +33,7 @@
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
<li><a asp-area="" asp-controller="Features" asp-action="Index">Features</a></li>
</ul>
@await Html.PartialAsync("_LoginPartial")
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment