principlecsharpMajor
Repository/Service Design Pattern
Viewed 0 times
patterndesignservicerepository
Problem
I use the Repository/Service design pattern in my projects and I have found something that might be a bit redundant. Am I writing any unnecessary code?
With that in mind, here is my structure:
This is an example POCO class, but as you will see I am using
My
My repository which implements
In this repository, I only do the minimal of what is required to query my database:
```
public class CompetitionService : IReposi
With that in mind, here is my structure:
public class Competition
{
public int Id { get; set; }
[Required] public string UserId { get; set; }
public string UserName { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DateModified { get; set; }
[Required] public string Name { get; set; }
}This is an example POCO class, but as you will see I am using
Generics so it can be anything:internal interface IRepository : IDisposable where TEntity : class
{
IList GetAll();
TEntity Get(int id);
void Save(TEntity model);
void Delete(int id);
}My
interface implements IDisposable and allows any class object to be set as TEntity:internal class CompetitionRepository : IRepository
{
private readonly string userId;
private readonly CompetitionProvider provider;
public CompetitionRepository(string userId) : this(userId, "DefaultConnection")
{
}
public CompetitionRepository(string userId, string connectionString)
{
this.userId = userId;
this.provider = new CompetitionProvider(connectionString);
}
public IList GetAll()
{
return provider.Get(this.userId);
}
public Competition Get(int id)
{
return GetAll().Where(model => model.Id == id).SingleOrDefault();
}
public void Save(Competition model)
{
provider.Save(model);
}
public void Delete(int id)
{
provider.Delete(id);
}
public void Dispose()
{
provider.Dispose();
}
}My repository which implements
IRepository, specifying Competition as TEntity. This repository queries my database hence the provider.In this repository, I only do the minimal of what is required to query my database:
```
public class CompetitionService : IReposi
Solution
You are on the right track. The separation of business logic (services) and data-access logic (repositories) is a good thing, I strongly recommend this. I created a generic repository implementing the
This greatly reduces the amount of duplicate code when you would use specific repositories. I use this in my services like:
As you may have noticed I use an IoC framework to inject the dependencies.
IRepository interface. It's slightly different than yours, but you get the point (I have a BaseEntity constraint, you can also use class for this):public class EfRepository : IRepository
where TEntity : BaseEntity, new()
{
private readonly IDbContext _context;
private IDbSet _entities;
public EfRepository(IDbContext context)
{
_context = context;
}
private IDbSet Entities
{
get { return _entities ?? (_entities = _context.Set()); }
}
public TEntity GetById(object id)
{
return Entities.Find(id);
}
public void Insert(TEntity entity)
{
Entities.Add(entity);
_context.SaveChanges();
}
public void Update(TEntity entity)
{
_context.SaveChanges();
}
public void Delete(int id)
{
// Create a new instance of an entity (BaseEntity) and add the id.
var entity = new TEntity
{
ID = id
};
// Attach the entity to the context and call the delete method.
Entities.Attach(entity);
Delete(entity);
}
public void Delete(TEntity entity)
{
Entities.Remove(entity);
_context.SaveChanges();
}
public IList Table
{
get { return Entities.ToList(); }
}
}This greatly reduces the amount of duplicate code when you would use specific repositories. I use this in my services like:
public class ProductService : IProductService
{
private readonly IRepository _productRepository;
public ProductService(IRepository productRepository)
{
_productRepository = productRepository;
}
public bool AddProduct(Product product)
{
// Validate etc.
_productRepository.Insert(product);
// return validation result.
return true;
}
}As you may have noticed I use an IoC framework to inject the dependencies.
Code Snippets
public class EfRepository<TEntity> : IRepository<TEntity>
where TEntity : BaseEntity, new()
{
private readonly IDbContext _context;
private IDbSet<TEntity> _entities;
public EfRepository(IDbContext context)
{
_context = context;
}
private IDbSet<TEntity> Entities
{
get { return _entities ?? (_entities = _context.Set<TEntity>()); }
}
public TEntity GetById(object id)
{
return Entities.Find(id);
}
public void Insert(TEntity entity)
{
Entities.Add(entity);
_context.SaveChanges();
}
public void Update(TEntity entity)
{
_context.SaveChanges();
}
public void Delete(int id)
{
// Create a new instance of an entity (BaseEntity) and add the id.
var entity = new TEntity
{
ID = id
};
// Attach the entity to the context and call the delete method.
Entities.Attach(entity);
Delete(entity);
}
public void Delete(TEntity entity)
{
Entities.Remove(entity);
_context.SaveChanges();
}
public IList<TEntity> Table
{
get { return Entities.ToList(); }
}
}public class ProductService : IProductService
{
private readonly IRepository<Product> _productRepository;
public ProductService(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public bool AddProduct(Product product)
{
// Validate etc.
_productRepository.Insert(product);
// return validation result.
return true;
}
}Context
StackExchange Code Review Q#33109, answer score: 25
Revisions (0)
No revisions yet.