I have project where I need to use C# and Entity Framework.
After my question here, I have decided to use Unit of Work and Repository patterns.
This is the first time when I'm using this. Can anyone tell me if I'm doing this right or I have to redesign something?
BTW: why do I have to set student.Group = null
in Service.StudentService.Update()
? Without this I'm getting exception. I don't understand when should I use student.Group
, and when student.GroupId
.
Entities:
namespace Model {
public abstract class BaseEntity {
[Timestamp]
public Byte[] TimeStamp{get; set;}
}
}
namespace Model {
public class Group : BaseEntity {
[Key]
public int GroupId {get; set;}
public string Name {get; set;}
public virtual ICollection<Student> Students {get; set;}
}
}
namespace Model {
public class Student : BaseEntity {
[Key]
public int StudentId {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string IndexNo {get; set;}
public int GroupId {get; set;}
[ForeignKey("GroupId")]
public virtual Group Group {get; set;}
public virtual ICollection<Registration> Registrations {get; set;}
}
}
Context:
namespace Model {
public class StorageContext : DbContext {
public DbSet<Group> Groups {get; set;}
public DbSet<Student> Students {get; set;}
...
}
}
Repository:
namespace Repository {
public class GenericRepository<TEntity> where TEntity : BaseEntity {
internal StorageContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(StorageContext context) {
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "") {
IQueryable<TEntity> query = dbSet;
if (filter != null) {
query = query.Where(filter);
}
foreach (var includeProperty in
includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) {
query = query.Include(includeProperty);
}
if (orderBy != null) {
return orderBy(query).ToList();
} else {
return query.ToList();
}
}
public virtual TEntity GetById(object id) {
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity) {
dbSet.Add(entity);
}
public virtual void Delete(object id) {
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entity) {
if (context.Entry(entity).State == EntityState.Detached) {
dbSet.Attach(entity);
}
dbSet.Remove(entity);
}
public virtual void Update (TEntity entity) {
dbSet.Attach(entity);
context.Entry(entity).State = EntityState.Modified;
}
}
}
UnitOfWorks:
namespace Repository {
public class GenericUnitOfWork<TEntity> : IDisposable where TEntity : BaseEntity{
public readonly StorageContext Context;
private bool _disposed;
private GenericRepository<TEntity> repository;
public GenericRepository<TEntity> GetRepository() {
return repository;
}
public GenericUnitOfWork(StorageContext context) {
this.Context = context;
repository = new GenericRepository<TEntity>(Context);
}
public IEnumerable<TEntity> Get() {
return repository.Get(null, null, "");
}
public virtual void Insert(TEntity entity) {
repository.Insert(entity);
Save();
}
public virtual void Update(TEntity entity) {
repository.Update(entity);
Save();
}
public void Delete(object id) {
repository.Delete(id);
Save();
}
public void Save() {
Context.SaveChanges();
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!this._disposed) {
if (disposing) {
Context.Dispose();
}
this._disposed = true;
}
}
}
}
namespace Repository {
public class GroupUnitOfWork : GenericUnitOfWork<Group>{
private GenericRepository<Group> repository;
public GroupUnitOfWork(StorageContext context) : base(context){
repository = new GenericRepository<Group>(Context);
}
public IEnumerable<Group> GetIncludeStudents() {
return repository.Get(null,null,"Students");
}
}
}
namespace Repository {
public class StudentUnitOfWork : GenericUnitOfWork<Student> {
private GenericRepository<Student> repository;
public StudentUnitOfWork(StorageContext context) : base(context){
repository = new GenericRepository<Student>(Context);
}
public IEnumerable<Student> GetByGroupId(object groupId) {
return repository.Get(s => s.GroupId == (int)groupId, null, "Group");
}
public override void Insert(Student student) {
repository.Insert(student);
Save();
}
public override void Update(Student student) {
repository.Update(student);
Save();
}
}
}
Services:
namespace Service {
public class GenericService<TEntity> where TEntity : BaseEntity{
protected StorageContext context;
public IEnumerable<TEntity> Get() {
using(var context = new StorageContext()) {
return new GenericUnitOfWork<TEntity>(context).Get();
}
}
public virtual void Insert(TEntity entity) {
using(var context = new StorageContext()) {
new GenericUnitOfWork<TEntity>(context).Insert(entity);
}
}
public virtual void Update(TEntity entity) {
using(var context = new StorageContext()) {
new GenericUnitOfWork<TEntity>(context).Update(entity);
}
}
public void Delete(object id) {
using(var context = new StorageContext()) {
new GenericUnitOfWork<TEntity>(context).Delete(id);
}
}
}
}
namespace Service {
public class GroupService : GenericService<Group>{
public IEnumerable<Group> GetIncludeStudents() {
using(var context = new StorageContext()) {
return new GroupUnitOfWork(context).GetIncludeStudents();
}
}
}
}
namespace Service {
public class StudentService : GenericService<Student> {
public IEnumerable<Student> GetByGroupId(object id) {
using(var context = new StorageContext()) {
return new StudentUnitOfWork(context).GetByGroupId(id);
}
}
public override void Update(Student student) {
using(var context = new StorageContext()) {
//without set student.Group to null I'm getting exception.
student.Group = null;
new StudentUnitOfWork(context).Update(student);
}
}
}
}
virtual
. \$\endgroup\$A referential integrity constraint violation occurred: The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.
exception \$\endgroup\$