Sono nuovo in questo modello di repository e ho visto molte configurazioni di repository + implementazioni UoW su Internet e non sono in grado di giungere a una conclusione su quale di esse sia corretta. Dopo aver esaminato molti link, sono riuscito a implementarne uno.
Considerando i seguenti punti in testa
- Dovrebbe soddisfare i principi SOLID
- Sii testabile
- Sii indipendente del quadro
- Essere indipendente dal DB
Ecco il codice dell'implementazione
IRepository generico
public interface IRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
T GetByKey(object id);
}
RepositoryBase
public abstract class RepositoryBase<D, T> : IRepository<T> where T : class where D : BaseDbContext
{
private D dataContext;
private readonly IDbSet<T> dbSet;
protected IDbFactory<D> DbFactory
{
get;
private set;
}
protected D DbContext
{
get { return dataContext ?? (dataContext = DbFactory.Init()); }
}
protected RepositoryBase(IDbFactory<D> dbFactory)
{
DbFactory = dbFactory;
dbSet = DbContext.Set<T>();
}
#region Implementation
public virtual void Add(T entity)
{
dbSet.Add(entity);
}
public virtual void Update(T entity)
{
dbSet.Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
dbSet.Remove(entity);
}
public T GetByKey(object id)
{
return dbSet.Find(id);
}
#endregion
}
IUnitofWork, UnitOfWork
public interface IUnitOfWork<D> where D : BaseDbContext
{
void Commit();
}
public class UnitOfWork<D> : IUnitOfWork<D> where D : BaseDbContext, new()
{
private readonly IDbFactory<D> dbFactory;
private D dbContext;
public UnitOfWork(IDbFactory<D> dbFactory)
{
this.dbFactory = dbFactory;
}
public D DbContext
{
get { return dbContext ?? (dbContext = dbFactory.Init()); }
}
public void Commit()
{
DbContext.SaveChanges();
}
}
IDBFactory, DBFactory
public interface IDbFactory<D> where D : BaseDbContext
{
D Init();
}
public class DbFactory<D> : Disposable, IDbFactory<D> where D : BaseDbContext, new()
{
D dbContext;
public D Init()
{
return dbContext ?? (dbContext = new D());
}
protected override void DisposeCore()
{
if (dbContext != null)
dbContext.Dispose();
}
}
BaseDbContext
public abstract class BaseDbContext : DbContext
{
public BaseDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
}
ProjectDbContext
public partial class ProjectDbContext : BaseDbContext
{
public ProjectDbContext()
: base("name=ProjectDbContext")
{
Database.SetInitializer<ProjectDbContext>(null);
}
}
ESEMPIO USO
Regolatore
public class StudentsController : BaseController
{
private IStudentBusiness objstudentbusiness;
public StudentsController(IStudentBusiness rstudentbusiness)
{
objstudentbusiness = rstudentbusiness;
}
public JsonResult LoadStudents()
{
var data = objstudentbusiness.ListStudents();
var jsonResult = Json(data, JsonRequestBehavior.AllowGet);
return jsonResult;
}
}
IStudentBAL, StudentBAL
public interface IStudentBAL
{
void SaveStudent(StudentDto student);
List<StudentDto> ListStudents();
}
public class StudentBAL : BusinessBase, IStudentBAL
{
private readonly IStudentRepository objStudentRepository;
private readonly IUnitOfWork<ProjectDbContext> objIUnitOfWork;
public StudentBAL(IStudentRepository rIStudentRepository, IUnitOfWork<ProjectDbContext> rIUnitOfWork)
{
try
{
objStudentRepository = rIStudentRepository;
objIUnitOfWork = rIUnitOfWork;
}
catch (Exception ex)
{
Log.Error(ex);
}
}
public List<StudentDto> ListStudents()
{
try
{
var tusrs = objStudentRepository.ListStudents() ?? new List<StudentDto>();
return tusrs;
}
catch (Exception ex)
{
Log.Error(ex);
}
return new List<StudentDto>();
}
}
IStudentRepository, StudentRepository
public interface IStudentRepository
{
void SaveStudent(Student Student);
StudentDto GetStudentByName(StudentDto Studentname);
Student GetStudentByID(int Studentid);
List<StudentDto> ListStudents();
}
public class StudentRepository : RepositoryBase<ProjectDbContext, Student>, IStudentRepository
{
public StudentRepository(IDbFactory<ProjectDbContext> dbFactory) : base(dbFactory)
{
}
public List<StudentDto> ListStudents()
{
var students = (from t in DbContext.Students
select new StudentDto
{
// all the required properties
}).ToList();
return students;
}
}
- L'iniezione delle dipendenze viene eseguita utilizzando AutoFac
- Il codice per la registrazione è omesso
Ti sto chiedendo se questa sembra una buona implementazione o mi sto perdendo qualcosa?
Apprezzerei qualsiasi feedback sulla mia implementazione che puoi offrire in merito a correttezza, efficienza e suggerimenti. Quindi, ecco le mie domande
- Questo è liberamente accoppiato?
- Ha qualche astrazione che perde e perché?
- Che cosa è necessario fare per passare da EF a MySQL db e quanto impegno richiederebbe per implementare le modifiche?
- Questo schema rompe i principi SOLID, Law o Demeter o qualsiasi legge orientata agli oggetti?
- Questo modello ha delle ridondanze di codice che non sono richieste?
- In che modo questa architettura che utilizza EF si ridimensionerà con un progetto contenente più di 100 entità di dominio e con ciascuna entità con almeno più di 10 campi. Sarà in seguito incubo di manutenzione?
-Tutte le critiche sono molto apprezzate !!