Skip to content

Commit eef458b

Browse files
author
Jeff Treuting
committed
GetAllQuery and FindAllQuery to return IQueryable
These are internal methods and by returning IQueryable we can keep it as a query (and on the server side if the LINQ provider does it that way) until the last minute. Previously we were returning IEnumerable and had a call to ToList() in these methods and so when doing a selector, each entire entity was returned and then the selector was supplied. This wasn't ideal because more data was transferred over the wire than needed to be. So now the FindAll and QueryAll that take a selector, call the GetAllQuery or FindAllQuery which keeps it as a Quyerable and then adds the .Select() part so it's part of the query. Then the FindAll or GetAll calls ToList() to take it from the server side and returne the actual results.
1 parent 5b2624d commit eef458b

3 files changed

Lines changed: 141 additions & 120 deletions

File tree

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,103 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Linq.Expressions;
5-
using SharpRepository.Repository.Caching;
6-
using SharpRepository.Repository.FetchStrategies;
7-
using SharpRepository.Repository.Queries;
8-
using SharpRepository.Repository.Specifications;
9-
10-
namespace SharpRepository.Repository
11-
{
12-
public abstract class LinqRepositoryBase<T, TKey> : RepositoryBase<T, TKey> where T : class
13-
{
14-
protected LinqRepositoryBase(ICachingStrategy<T, TKey> cachingStrategy = null) : base(cachingStrategy)
15-
{
16-
}
17-
18-
public override IQueryable<T> AsQueryable()
19-
{
20-
return BaseQuery();
21-
}
22-
23-
protected abstract IQueryable<T> BaseQuery(IFetchStrategy<T> fetchStrategy = null);
24-
25-
protected override T GetQuery(TKey key)
26-
{
27-
return FindQuery(ByPrimaryKeySpecification(key));
28-
}
29-
30-
protected override T FindQuery(ISpecification<T> criteria)
31-
{
32-
return criteria.SatisfyingEntityFrom(BaseQuery());
33-
}
34-
35-
protected override T FindQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions)
36-
{
37-
if (queryOptions == null)
38-
return FindQuery(criteria);
39-
40-
var query = queryOptions.Apply(BaseQuery());
41-
42-
return criteria.SatisfyingEntityFrom(query);
43-
}
44-
45-
protected override IEnumerable<T> GetAllQuery()
46-
{
47-
return BaseQuery().ToList();
48-
}
49-
50-
protected override IEnumerable<T> GetAllQuery(IQueryOptions<T> queryOptions)
51-
{
52-
if (queryOptions == null)
53-
return GetAllQuery();
54-
55-
var query = BaseQuery();
56-
57-
return queryOptions.Apply(query).ToList();
58-
}
59-
60-
protected override IEnumerable<T> FindAllQuery(ISpecification<T> criteria)
61-
{
62-
var query = BaseQuery(criteria.FetchStrategy);
63-
return criteria.SatisfyingEntitiesFrom(query).ToList();
64-
}
65-
66-
protected override IEnumerable<T> FindAllQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions)
67-
{
68-
if (queryOptions == null)
69-
return FindAllQuery(criteria);
70-
71-
var query = BaseQuery(criteria.FetchStrategy);
72-
73-
query = criteria.SatisfyingEntitiesFrom(query);
74-
75-
return queryOptions.Apply(query).ToList();
76-
}
77-
78-
public override IEnumerator<T> GetEnumerator()
79-
{
80-
return BaseQuery().GetEnumerator();
81-
}
82-
83-
public override IRepositoryQueryable<TResult> Join<TJoinKey, TInner, TResult>(IRepositoryQueryable<TInner> innerRepository, Expression<Func<T, TJoinKey>> outerKeySelector, Expression<Func<TInner, TJoinKey>> innerKeySelector, Expression<Func<T, TInner, TResult>> resultSelector)
84-
{
85-
var innerQuery = innerRepository.AsQueryable();
86-
var outerQuery = BaseQuery();
87-
88-
var innerType = innerRepository.GetType();
89-
var outerType = GetType();
90-
91-
// if these are 2 different Repository types then let's bring down each query into memory so that they can be joined
92-
// if they are the same type then they will use the native IQueryable and take advantage of the back-end side join if possible
93-
if (innerType.Name != outerType.Name)
94-
{
95-
innerQuery = innerQuery.ToList().AsQueryable();
96-
outerQuery = outerQuery.ToList().AsQueryable();
97-
return new CompositeRepository<TResult>(outerQuery.Join(innerQuery, outerKeySelector, innerKeySelector, resultSelector));
98-
}
99-
100-
return new CompositeRepository<TResult>(outerQuery.Join(innerQuery, outerKeySelector, innerKeySelector, resultSelector));
101-
}
102-
}
103-
}
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using SharpRepository.Repository.Caching;
6+
using SharpRepository.Repository.FetchStrategies;
7+
using SharpRepository.Repository.Queries;
8+
using SharpRepository.Repository.Specifications;
9+
10+
namespace SharpRepository.Repository
11+
{
12+
public abstract class LinqRepositoryBase<T, TKey> : RepositoryBase<T, TKey> where T : class
13+
{
14+
protected LinqRepositoryBase(ICachingStrategy<T, TKey> cachingStrategy = null) : base(cachingStrategy)
15+
{
16+
}
17+
18+
public override IQueryable<T> AsQueryable()
19+
{
20+
return BaseQuery();
21+
}
22+
23+
protected abstract IQueryable<T> BaseQuery(IFetchStrategy<T> fetchStrategy = null);
24+
25+
protected override T GetQuery(TKey key)
26+
{
27+
return FindQuery(ByPrimaryKeySpecification(key));
28+
}
29+
30+
protected override T FindQuery(ISpecification<T> criteria)
31+
{
32+
return criteria.SatisfyingEntityFrom(BaseQuery());
33+
}
34+
35+
protected override T FindQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions)
36+
{
37+
if (queryOptions == null)
38+
return FindQuery(criteria);
39+
40+
var query = queryOptions.Apply(BaseQuery());
41+
42+
return criteria.SatisfyingEntityFrom(query);
43+
}
44+
45+
protected override IQueryable<T> GetAllQuery()
46+
{
47+
return BaseQuery();
48+
}
49+
50+
protected override IQueryable<T> GetAllQuery(IQueryOptions<T> queryOptions)
51+
{
52+
if (queryOptions == null)
53+
return GetAllQuery();
54+
55+
var query = BaseQuery();
56+
57+
return queryOptions.Apply(query);
58+
}
59+
60+
protected override IQueryable<T> FindAllQuery(ISpecification<T> criteria)
61+
{
62+
var query = BaseQuery(criteria.FetchStrategy);
63+
return criteria.SatisfyingEntitiesFrom(query);
64+
}
65+
66+
protected override IQueryable<T> FindAllQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions)
67+
{
68+
if (queryOptions == null)
69+
return FindAllQuery(criteria);
70+
71+
var query = BaseQuery(criteria.FetchStrategy);
72+
73+
query = criteria.SatisfyingEntitiesFrom(query);
74+
75+
return queryOptions.Apply(query);
76+
}
77+
78+
public override IEnumerator<T> GetEnumerator()
79+
{
80+
return BaseQuery().GetEnumerator();
81+
}
82+
83+
public override IRepositoryQueryable<TResult> Join<TJoinKey, TInner, TResult>(IRepositoryQueryable<TInner> innerRepository, Expression<Func<T, TJoinKey>> outerKeySelector, Expression<Func<TInner, TJoinKey>> innerKeySelector, Expression<Func<T, TInner, TResult>> resultSelector)
84+
{
85+
var innerQuery = innerRepository.AsQueryable();
86+
var outerQuery = BaseQuery();
87+
88+
var innerType = innerRepository.GetType();
89+
var outerType = GetType();
90+
91+
// if these are 2 different Repository types then let's bring down each query into memory so that they can be joined
92+
// if they are the same type then they will use the native IQueryable and take advantage of the back-end side join if possible
93+
if (innerType.Name != outerType.Name)
94+
{
95+
innerQuery = innerQuery.ToList().AsQueryable();
96+
outerQuery = outerQuery.ToList().AsQueryable();
97+
return new CompositeRepository<TResult>(outerQuery.Join(innerQuery, outerKeySelector, innerKeySelector, resultSelector));
98+
}
99+
100+
return new CompositeRepository<TResult>(outerQuery.Join(innerQuery, outerKeySelector, innerKeySelector, resultSelector));
101+
}
102+
}
103+
}

SharpRepository.Repository/RepositoryBase.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System;
2-
using System.Collections;
1+
using System;
2+
using System.Collections;
33
using System.Reflection;
44
using System.Collections.Generic;
55
using System.Linq;
@@ -52,8 +52,8 @@ protected RepositoryBase(ICachingStrategy<T, TKey> cachingStrategy = null)
5252
public abstract IQueryable<T> AsQueryable();
5353

5454
// These are the actual implementation that the derived class needs to implement
55-
protected abstract IEnumerable<T> GetAllQuery();
56-
protected abstract IEnumerable<T> GetAllQuery(IQueryOptions<T> queryOptions);
55+
protected abstract IQueryable<T> GetAllQuery();
56+
protected abstract IQueryable<T> GetAllQuery(IQueryOptions<T> queryOptions);
5757

5858
public IEnumerable<T> GetAll()
5959
{
@@ -72,9 +72,9 @@ public IEnumerable<TResult> GetAll<TResult>(Expression<Func<T, TResult>> selecto
7272
{
7373
if (selector == null) throw new ArgumentNullException("selector");
7474

75-
return GetAll(queryOptions)
76-
.AsQueryable()
77-
.Select(selector);
75+
return GetAllQuery(queryOptions)
76+
.Select(selector)
77+
.ToList();
7878
}
7979

8080
// These are the actual implementation that the derived class needs to implement
@@ -105,8 +105,8 @@ public TResult Get<TResult>(TKey key, Expression<Func<T, TResult>> selector)
105105
}
106106

107107
// These are the actual implementation that the derived class needs to implement
108-
protected abstract IEnumerable<T> FindAllQuery(ISpecification<T> criteria);
109-
protected abstract IEnumerable<T> FindAllQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions);
108+
protected abstract IQueryable<T> FindAllQuery(ISpecification<T> criteria);
109+
protected abstract IQueryable<T> FindAllQuery(ISpecification<T> criteria, IQueryOptions<T> queryOptions);
110110

111111
public IEnumerable<T> FindAll(ISpecification<T> criteria, IQueryOptions<T> queryOptions = null)
112112
{
@@ -123,7 +123,7 @@ public IEnumerable<TResult> FindAll<TResult>(ISpecification<T> criteria, Express
123123
{
124124
if (criteria == null) throw new ArgumentNullException("criteria");
125125

126-
return FindAll(criteria, queryOptions).AsQueryable().Select(selector).ToList();
126+
return FindAllQuery(criteria, queryOptions).Select(selector).ToList();
127127
}
128128

129129
public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate, IQueryOptions<T> queryOptions = null)
@@ -359,12 +359,12 @@ private static PropertyInfo GetPropertyCaseInsensitive(IReflect type, string pro
359359
const BindingFlags bindingFlags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
360360

361361
return type.GetProperty(propertyName, bindingFlags, null, propertyType, new Type[0], new ParameterModifier[0]);
362-
}
363-
364-
public abstract IEnumerator<T> GetEnumerator();
365-
IEnumerator IEnumerable.GetEnumerator()
366-
{
367-
return GetEnumerator();
368-
}
362+
}
363+
364+
public abstract IEnumerator<T> GetEnumerator();
365+
IEnumerator IEnumerable.GetEnumerator()
366+
{
367+
return GetEnumerator();
368+
}
369369
}
370370
}

SharpRepository.Tests.Integration/RepositoryGetAllTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,27 @@ public void GetAll_With_Selector_Should_Return_Every_Item(IRepository<Contact, s
5959
result.Count().ShouldEqual(5);
6060
}
6161

62+
[ExecuteForAllRepositories]
63+
public void GetAll_With_Anonymous_Selector_Should_Return_Every_Item(IRepository<Contact, string> repository)
64+
{
65+
for (var i = 1; i <= 5; i++)
66+
{
67+
var contact = new Contact { Name = "Test User " + i };
68+
repository.Add(contact);
69+
}
70+
71+
var results = repository.GetAll(c => new {c.Name, c.Title});
72+
73+
var total = 0;
74+
foreach (var result in results)
75+
{
76+
result.Name.ShouldStartWith("Test User");
77+
total++;
78+
}
79+
80+
total.ShouldEqual(5);
81+
}
82+
6283
[ExecuteForAllRepositories]
6384
public void GetAll_With_Selector_Should_Return_Every_Items_With_Paging(IRepository<Contact, string> repository)
6485
{

0 commit comments

Comments
 (0)