Generic Repository with LLBLGen

Posts   
 
    
Posts: 15
Joined: 09-Oct-2008
# Posted on: 07-Dec-2013 02:03:37   

I'm trying to implement a generic repository that will map the LLBLGen Entities into POCO Models.

I got a repository base class with 2 generics: LlblEnt obviously will be an Entity from my llbl EntityClasses, while Model will be the Poco.

This is the base class:


    public abstract class RepositoryBase<LlblEnt, Model> where LlblEnt : EntityBase
    {

        public IEnumerable<Model> Get()
        {
            LinqMetaData Lm = new LinqMetaData();
            return Lm.GetQueryableForEntity<LlblEnt>().Select(f => Mapper.Map<LlblEnt, Model>(f)).ToList();

        }
    }

This is the Real one:


    class UserRepository : RepositoryBase<UserEntity, User> {   }

The problem is that when I use the repository class on a different Layer it will require a reference to SD.LLBLGen.Pro.ORMSupportClasses and to the Entity also. And I'm working hard to avoid it stuck_out_tongue_winking_eye how can I fix it, so that the Generic repo will work without references?

Also, there is a sample code of a basic implementation of a Generic repository for LLBLGen?

Thanks.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Dec-2013 06:24:36   

Whenever you use IEntity, you will need to use ORMSupportClasses. Even if you just pass the entity name as string and use reflection inside, you need to have ORMSupportClasses assembly in the final output directory.

As for your second question: there are some repository codes in the forums but not that much different than yours, except that you are using some kind of Dictionary with POCOs.

David Elizondo | LLBLGen Support Team
Posts: 15
Joined: 09-Oct-2008
# Posted on: 07-Dec-2013 11:30:49   

Well yes, using the explicit constructor I completely agree with you, but I'm sure that on the best practices of the repository pattern there is also a factory who decouple the the business layer from the constructor.

I will rephrase my question:

I'm trying to decouple the Bll from the Dal using some interfaces and a Factory patter. Data.Contracts containing the interfaces will be referenced on my Bll.

I can not use the concrete Implementations of the Repository since they are inheriting from some classes that I do not want on my Bll.

DataRepositoryBase in particular leverage LLBLGen Pro, and will map the LLBL Entities on POCO models.

following my code:

I got a DataRepositoryBase:


    public abstract class DataRepositoryBase<LlblEnt, Model> where LlblEnt : EntityBase, new() where Model : new()
    {
        public IEnumerable<Model> Get() {   // Other code here...   }
    }

I got a concrete implementation of the abstract generic:


   public class UserRepository : DataRepositoryBase<UserEntity, User>, IUserRepository
    {
        public UserRepository()  {   }
    }

I got a Factory to build any Repository:


    public class DataRepositoryFactory : IDataRepositoryFactory
    {
            public T GetDataRepository<T>() where T : IDataRepository, new()
            {   
                return new T(); 
            }
    }

I got the interfaces:


    public interface IDataRepository<T> : IDataRepository   where T : class, new()
    {
        IEnumerable<T> Get();
    }

    public interface IUserRepository : IDataRepository  {   }

    public interface IDataRepository {  }

And finally I'm trying to build the repository using the factory:


    static void Main(string[] args)
    {
        IDataRepositoryFactory _DataRepositoryFactory;
        IUserRepository AptRep = _DataRepositoryFactory.GetDataRepository<IUserRepository>();
    }

An finally I got my error:

'Data.Contracts.IUserRepository' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Data.Contracts.IDataRepositoryFactory.GetDataRepository()'

It seems quite obvious that the "return new T()" will try to create and Interface, and so will not work.

My question is: Which is the correct implementation to Decouple the code on the Business layer using the factory pattern? I can not use the concrete implementation UserRepository since it inherits from classes that I do not want in the BLL.

Any help would be appreciated.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39765
Joined: 17-Aug-2003
# Posted on: 10-Dec-2013 10:02:42   

(not really an llblgen question. Moved to architecture)

Why is there a factory at all, if all it does is simply call the ctor? You also pass in an interface and expect the method to create a concrete type instance, which can't work of course, you have to specify the concrete type.

I understand you don't want the concrete type specified, as that would force you to reference assemblies you don't want to depend on. What's often done is (elsewhere, outside your BL) to create a factory factory (yes, really simple_smile ) which given a parameter gives you a factory for the type related to the parameter. This means you have to define somewhere that parameter X gives factory Y. You could build this with reflection, e.g. find all interfaces of a given type in assembly, then all classes which implement these interfaces and you can then create the instances of the classes if the interface they implement is given. Or define them hardcoded.

Keep in mind that using interfaces isn't really helpful if you make them generic. Using interfaces is already a way to implement generic code, adding generics to them is redundant.

Frans Bouma | Lead developer LLBLGen Pro