Design of Service Layer using OpenAccess

4 posts, 1 answers
  1. Abdel
    Abdel avatar
    4 posts
    Member since:
    Sep 2012

    Posted 24 Sep 2012 Link to this post

    I am building a service layer and have my data layer built using OpenAccess ORM. I have my service interface as below:

    public interface IDataService<T>
    {
        void Create(T item);
        void Update(T item);
        void Delete(T item);
        T Get(T item);
        IEnumerable<T> ListAll();
    }

    The Concrete classes work fine as long as I am doing a CRUD operation and using ListAll method. But I need to provide feature to filter my entites using some criterias. My issue is, I don't want method like GetManagers(), GetEmployeesWithPayGrade(int grade) etc.

    Hence, I am looking for a way to make my entity queryable in a generic way. Can somebody point me to the right direction and 
    best practice with this matter?

    Thanks!
  2. Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 24 Sep 2012 Link to this post

    Hi Abdel,

    Based on your description you should be able to easily utilize Data Services v2 or v3 and Add OpenAccess Service wizard.
    Data Service offer support for the same contract that you have defined and will require very little code and configuration to be written.
    You can find out more information about Data Services on MSDN here.
    You can see how Add OpenAccess Service wizard produces the service layer for you in our online documentation.

    One important note: when you are consuming a Data Service you can use the same client code as if the service was defined using Microsoft Entity Framework model and you can use Add Service Reference option in Visual Studio.

    If you need any further assistance in choosing the right service type or about the implementation of Data Service do not hesitate to contact us.

    Regards,
    Viktor Zhivkov
    the Telerik team
    Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
  3. DevCraft banner
  4. Abdel
    Abdel avatar
    4 posts
    Member since:
    Sep 2012

    Posted 25 Sep 2012 Link to this post

    Hi Viktor,
     Thanks for your response. I am not looking for a web service. My interface is a Repository interface. I am trying to make it very generic and flexible. 

    Interface:
    public interface IDataService<T>
    {
        void Create(T item);
        void Update(T item);
        void Delete(T item);
        T Get(Expression<Func<T, bool>> predicate);
        IQueryable<T> GetAll(Expression<Func<T, bool>> predicate);
     
    }

    My Data Service ( Repository ) is :
    public class DataService<T> : IDataService<T> where T : class
        {
            private EntitiesModel dbContext;
     
            public DataService(EntitiesModel context)
            {
                this.dbContext = context;
            }
     
            public void Create(T item)
            {
                dbContext.Add(item);
                dbContext.SaveChanges();
            }
     
            public void Update(T item)
            {
                throw new NotImplementedException();
            }
     
            public void Delete(T item)
            {
                throw new NotImplementedException();
            }
     
            public T Get(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
            {
                if (predicate != null)
                    return dbContext.GetAll<T>().SingleOrDefault<T>(predicate);
                else
                    return null;
            }
     
            public IQueryable<T> GetAll(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
            {
                if (predicate != null)
                    return dbContext.GetAll<T>().Where(predicate);
                else
                    return dbContext.GetAll<T>();
            }
     
     
            public IQueryable<T> GetAll()
            {
                return dbContext.GetAll<T>();
            }
        }


    What I am looking for is to make my repository queryable. For example:
     
    IDataService<Person> service = new DataService<Person>(dbContext);
    service.GetAll().Count();
    service.GetAll().Where( some conditions).Single();
     etc.. basically, trying to make it chainable
    How can I do it?
  5. Answer
    Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 27 Sep 2012 Link to this post

    Hello Abdel,

    You definition of IDataService/DataService interface already allows you to chain LINQ statements.

    There are some improvements that you can see in the code snippet below. See my comments inline for more information.
    01.public class DataService<T, TContext> //TContext enables you to use this class with any OpenAccess context model, not just with EntitiesModel
    02.    : IDataService<T>
    03.    where T : class //could be a problem if you are using Code-First and you have defined an entity as struct (Value Type)
    04.    where TContext : Telerik.OpenAccess.OpenAccessContext
    05.{
    06.    private readonly TContext dbContext; //readonly is a safe guard to prevents change of your context
    07. 
    08.    public DataService(TContext context)
    09.    {
    10.        if (context == null) //the context is absolute must when initilizing
    11.            throw new ArgumentNullException("context");
    12. 
    13.        this.dbContext = context;
    14.    }
    15. 
    16.    public void Create(T item)
    17.    {
    18.        if (item == null) // OpenAccess does not allow null to be added
    19.            throw new ArgumentNullException("item");
    20. 
    21.        dbContext.Add(item);
    22.        dbContext.SaveChanges();
    23.    }
    24. 
    25.    public void Update(T item)
    26.    {
    27.        if (item == null)
    28.            throw new ArgumentNullException("item");
    29. 
    30.        throw new NotImplementedException();
    31.    }
    32. 
    33.    public void Delete(T item)
    34.    {
    35.        if (item == null)
    36.            throw new ArgumentNullException("item");
    37. 
    38.        throw new NotImplementedException();
    39.    }
    40. 
    41.    public T Get(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    42.    {
    43.        // better do not allow calling with null predicate
    44.        // entirely up to, so feel free to ignore this check
    45.        if (predicate == null)
    46.            throw new ArgumentNullException("predicate");
    47. 
    48.        if (predicate != null)
    49.            return dbContext.GetAll<T>().SingleOrDefault<T>(predicate);
    50.        else
    51.            return null;
    52.    }
    53. 
    54.    public IQueryable<T> GetAll(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    55.    {
    56.        // you have defined a parameterless overload already, do not overlap implementation unless necessary
    57.        // again if your scenario will benefit from having this dualisting behaviour just ignore the check and use the original version
    58.        if (predicate == null)
    59.            throw new ArgumentNullException("predicate");
    60. 
    61.        return dbContext.GetAll<T>().Where(predicate);
    62.    }
    63. 
    64.    public IQueryable<T> GetAll()
    65.    {
    66.        return dbContext.GetAll<T>();
    67.    }
    68.}

    You are welcome to share your comments on the proposed code snippet.

    Regards,
    Viktor Zhivkov
    the Telerik team
    Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
Back to Top