Note that there are some explanatory texts on larger screens.

plurals
  1. POEntityFramework with UnitOfWork to Service pattern
    primarykey
    data
    text
    <p>I have the following layers in my application.</p> <ol> <li>Repository.Ef (this handle the context of ef)</li> <li>Entities (here is all entities for ef)</li> <li>Core (This layer handle all business and works like a wrapper between Ef &lt;> Gui)</li> <li>Gui (This is the User interface)</li> </ol> <p>I have interface for most of the classes and use DI, but this version is compressed to only show the classes.</p> <p>This is the UnitOfWork, that hold the DbContext in my Repository.Ef layer.</p> <pre><code>public class UnitOfWork : DbContext, IUnitOfWork { static UnitOfWork() { Database.SetInitializer&lt;UnitOfWork&gt;(null); } public UnitOfWork() : base("Name=SalesDb") { } public IRepository&lt;T&gt; Repository&lt;T&gt;() where T : EntityBase { return new Repository&lt;T&gt;(Set&lt;T&gt;()); } public void ApplyStateChanges() { foreach (var dbEntityEntry in ChangeTracker.Entries()) { var entityState = dbEntityEntry.Entity as EntityBase; if (entityState == null) throw new InvalidCastException("All entites must implement the IObjectState interface, " + "this interface must be implemented so each entites state can explicitely determined when updating graphs."); dbEntityEntry.State = StateHelper.ConvertState(entityState.State); } } #region DBSET // HERE IS ALL MY DBSETS #endregion protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove&lt;PluralizingTableNameConvention&gt;(); } public override int SaveChanges() { ApplyStateChanges(); return base.SaveChanges(); } } </code></pre> <p>And this is my Repository (same layer as UnitOfWork)</p> <pre><code> public class Repository&lt;T&gt; : IRepository&lt;T&gt; where T : class, IEntity { private readonly DbSet&lt;T&gt; _dbSet; public Repository(DbSet&lt;T&gt; dbSet) { _dbSet = dbSet; } public IQueryable&lt;T&gt; Query() { var data = _dbSet.AsQueryable(); return data; } public IEnumerable&lt;T&gt; GetAll() { return _dbSet; } public IEnumerable&lt;T&gt; Find(Expression&lt;Func&lt;T, bool&gt;&gt; predicate) { return _dbSet.Where(predicate); } public T FindById(int id) { return _dbSet.Find(id); } public void Add(T entity) { entity.State = ObjectState.Added; _dbSet.Add(entity); } public void Remove(T entity) { entity.State = ObjectState.Deleted; _dbSet.Remove(entity); } public void Update(T entity) { entity.State = ObjectState.Modified; _dbSet.Attach(entity); } } </code></pre> <p>Here is my Core layer (Business rules and the wrapper between GUI layer) The following is my ServiceUnit.</p> <pre><code> public class ServiceUnit { internal readonly IUnitOfWork unitOfWork; public ServiceUnit() { unitOfWork = new UnitOfWork(); } public void Add&lt;T&gt;(T entity, int marketId, string username) where T : EntityBase { entity.MarketId = marketId; entity.ChUser = username; entity.ChTime = DateTime.Now; entity.Deleted = false; unitOfWork.Repository&lt;T&gt;().Add(entity); unitOfWork.SaveChanges(); } public void Update&lt;T&gt;(T entity, string username) where T : EntityBase { entity.ChUser = username; entity.ChTime = DateTime.Now; unitOfWork.Repository&lt;T&gt;().Update(entity); unitOfWork.SaveChanges(); } public void Remove&lt;T&gt;(int id) where T : EntityBase { var entity = unitOfWork.Repository&lt;T&gt;().FindById(id); entity.Deleted = true; entity.ChTime = DateTime.Now; unitOfWork.Repository&lt;T&gt;().Update(entity); unitOfWork.SaveChanges(); } public IEnumerable&lt;T&gt; Find&lt;T&gt;(int? marketId = null, Expression&lt;Func&lt;T, bool&gt;&gt; predicate = null) where T : EntityBase { var data = unitOfWork.Repository&lt;T&gt;() .Find(predicate); if (marketId != null) { data = data .Where(t =&gt; t.MarketId == marketId); } return data; } public T FindById&lt;T&gt;(int id) where T : EntityBase { return unitOfWork.Repository&lt;T&gt;().FindById(id); } public void Commit() { unitOfWork.SaveChanges(); } } </code></pre> <p>And this is a Service class to handle all Contact functions</p> <pre><code> public class ContactService { private readonly ServiceUnit serviceUnit; private IRepository&lt;Contact&gt; contactRep { get { return serviceUnit.unitOfWork.Repository&lt;Contact&gt;(); } } private IRepository&lt;ContactUserProfile&gt; contactUserProfileRep { get { return serviceUnit.unitOfWork.Repository&lt;ContactUserProfile&gt;(); } } public ContactService(ServiceUnit serviceUnit) { this.serviceUnit = serviceUnit; } public IEnumerable&lt;ContactUserProfile&gt; GetContactsForUser(int marketId, int userId, int status) { return contactUserProfileRep .Query() .Where(u =&gt; u.Contact.MarketId == marketId) .Where(cup =&gt; cup.UserProfileId == userId) .Where(c =&gt; c.Deleted == false) .Where(c =&gt; c.Contact.Status == status) .ToList(); } } </code></pre> <p>Lets explain how i use all this code. First of all, i dont want to have dependency for entity framework in my gui layer, and with this service wrapper (ServiceUnit) i dont have to reference entity framework.</p> <p>Every page request create a ServiceUnit, and the ServiceUnit create a new UnitOfWork that hold whole the EntityFramework context.</p> <p>For example, the contact page create a ServiceUnit and a ServiceContact and inject the Service unit, so i have the same context for the request.</p> <p>Can this pattern cause any problem? Just want to se if i missed something importent here.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload