New Posts New Posts RSS Feed: Cocktail/Temphire - Unit of Work & Repository Architecture
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Cocktail/Temphire - Unit of Work & Repository Architecture

 Post Reply Post Reply
Author
DanielK View Drop Down
Newbie
Newbie


Joined: 05-Feb-2013
Posts: 2
Post Options Post Options   Quote DanielK Quote  Post ReplyReply Direct Link To This Post Topic: Cocktail/Temphire - Unit of Work & Repository Architecture
    Posted: 05-Feb-2013 at 2:53pm
I am just studying the Temphire reference application and came across a topic I do not fully understand.
Maybe you can bring some light on the problem and recommend a best practice approach.

Let's say I would like to extend the StaffingResourceRepository by some custom data selection method, e.g.

public async Task<IEnumerable<StaffingResource>> FindAll()
{
// Get all StaffingResources
var query = EntityManager.StaffingResources;
return await query.ExecuteAsync();
}

In the StaffingResourceDetailViewModel I would like to use this method but I can't because
in the ResourceMgtUnitOfWork the StaffingResources is defined as IRepository<StaffingResource> and not as StaffingResourceRepository.

Could you please explain why you use IRepository<StaffingResource> and not StaffingResourceRepository in the ResourceMgtUnitOfWork
and what is the best approach if I would like to use the "custom" StaffingResourceRepository in a ViewModel instead of the generic one.

Thank you for your assistance
Daniel
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 05-Feb-2013 at 7:10pm
Well, the point of an interface is always the same. To define an abstract contract that allows for different implementations of said contract. For example for unit testing you can substitute the Cocktail implementation of the repository with a fake implementation that returns hard-coded data or you can easily replace an existing repository with an optimized implementation if you run into performance problems later in the lifecycle without having to change the parts of your application that interact with the repository. Interfaces are a pretty fundamental concept in modern programming languages. 

If you don't like the contract that IRepository<T> provides, then you simply create your own interface that either extends IRepository<T> or completely replaces it. 
Back to Top
DanielK View Drop Down
Newbie
Newbie


Joined: 05-Feb-2013
Posts: 2
Post Options Post Options   Quote DanielK Quote  Post ReplyReply Direct Link To This Post Posted: 06-Feb-2013 at 1:37am
Thank you for your reply.
The concept of interfaces is known but if working with demo applications it’s not always easy to understand if something was implemented just because for the sake of convenience.
However. If I understood you right. You recommend something like this, right?

Thanks
Daniel

namespace DomainServices.Repositories
{
    public interface IStaffingResourceRepository : IRepository<StaffingResource>
    {
        Task<IEnumerable<StaffingResource>> FindAll();
    }
}

namespace DomainServices.Repositories
{
    public class StaffingResourceRepository : Repository<StaffingResource>, IStaffingResourceRepository
    {
        public StaffingResourceRepository(IEntityManagerProvider<TempHireEntities> entityManagerProvider)
            : base(entityManagerProvider)
        {
        }

        public new TempHireEntities EntityManager
        {
            get { return (TempHireEntities) base.EntityManager; }
        }

        public Task<IEnumerable<StaffingResource>> FindAll()
        {
            // Get all StaffingResources
            var query = EntityManager.StaffingResources;
            return query.ExecuteAsync();
        }

        protected override IEntityQuery GetKeyQuery(params object[] keyValues)
        {
            return EntityManager.StaffingResources
               .Where(r => r.Id == (Guid) keyValues[0])
               .Include(r => r.Addresses)
               .Include(r => r.PhoneNumbers);
        }
    }
}

namespace DomainServices
{
    public interface IResourceMgtUnitOfWork : IUnitOfWork
    {
        // Factories
        IFactory<StaffingResource> StaffingResourceFactory { get; }

        // Repositories
        IRepository<AddressType> AddressTypes { get; }
        IRepository<State> States { get; }
        IRepository<PhoneNumberType> PhoneNumberTypes { get; }
        IRepository<RateType> RateTypes { get; }
        IStaffingResourceRepository StaffingResources { get; }

        // Services
        IStaffingResourceSearchService Search { get; }
    }
}
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 06-Feb-2013 at 5:46am
Yep, you got it. BTW, FindAll would be a redundant method. This functionality is already provided by AllAsync().
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down