Print Page | Close Window

Cocktail/Temphire - Unit of Work & Repository Architecture

Printed From: IdeaBlade
Category: Cocktail
Forum Name: Community Forum
Forum Discription: A professional application framework using Caliburn.Micro and DevForce
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=3979
Printed Date: 09-Apr-2020 at 9:22am


Topic: Cocktail/Temphire - Unit of Work & Repository Architecture
Posted By: DanielK
Subject: Cocktail/Temphire - Unit of Work & Repository Architecture
Date 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



Replies:
Posted By: mgood
Date 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. 


Posted By: DanielK
Date 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; }
    }
}


Posted By: mgood
Date 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().



Print Page | Close Window