This is a migrated thread and some comments may be shown as answers.

Design of Service Layer using OpenAccess

3 Answers 79 Views
Data Access Free Edition
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Abdel
Top achievements
Rank 1
Abdel asked on 24 Sep 2012, 11:15 AM
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!

3 Answers, 1 is accepted

Sort by
0
Viktor Zhivkov
Telerik team
answered on 24 Sep 2012, 04:18 PM
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!
0
Abdel
Top achievements
Rank 1
answered on 25 Sep 2012, 11:32 AM
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?
0
Accepted
Viktor Zhivkov
Telerik team
answered on 27 Sep 2012, 10:42 AM
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!
Tags
Data Access Free Edition
Asked by
Abdel
Top achievements
Rank 1
Answers by
Viktor Zhivkov
Telerik team
Abdel
Top achievements
Rank 1
Share this question
or