Skip to content
This repository was archived by the owner on Jan 27, 2022. It is now read-only.

Commit 46f38d9

Browse files
iscottb122Iain Scott
authored andcommitted
Change Query methods to take predicate instead of returning IQueryable.
1 parent 2392f64 commit 46f38d9

7 files changed

Lines changed: 35 additions & 24 deletions

File tree

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,7 @@ internal sealed class TransactionRepository : ITransactionRepository
185185

186186
public IEnumerable<Transaction> GetAllSentBy(AccountId accountId)
187187
{
188-
return _entityFacade.Query()
189-
.Where(t => t.Sender == accountId)
190-
.AsEnumerable();
188+
return _entityFacade.Query(t => t.Sender == accountId);
191189
}
192190

193191
...
@@ -209,8 +207,7 @@ internal sealed class AccountTypeRepository : IAccountTypeRepository
209207

210208
public IEnumerable<AccountType> GetAll()
211209
{
212-
return _valueObjectFacade.Query()
213-
.AsEnumerable();
210+
return _valueObjectFacade.Query();
214211
}
215212

216213
...

src/Winton.DomainModelling.DocumentDb/EntityFacade.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Linq;
7+
using System.Linq.Expressions;
68
using System.Net;
79
using System.Threading.Tasks;
810
using Microsoft.Azure.Documents;
@@ -46,13 +48,15 @@ public async Task Delete(TEntityId id)
4648
await _documentClient.DeleteDocumentAsync(GetUri(id));
4749
}
4850

49-
public IQueryable<TEntity> Query()
51+
public IEnumerable<TEntity> Query(Expression<Func<TEntity, bool>> predicate = null)
5052
{
5153
string entityType = EntityDocument<TEntity, TEntityId>.GetDocumentType();
5254

5355
return _documentClient.CreateDocumentQuery<EntityDocument<TEntity, TEntityId>>(GetUri())
5456
.Where(x => x.Type == entityType)
55-
.Select(x => x.Entity);
57+
.Select(x => x.Entity)
58+
.Where(predicate ?? (x => true))
59+
.AsEnumerable();
5660
}
5761

5862
public async Task<TEntity> Read(TEntityId id)

src/Winton.DomainModelling.DocumentDb/IEntityFacade.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33

44
using System;
5-
using System.Linq;
5+
using System.Collections.Generic;
6+
using System.Linq.Expressions;
67
using System.Threading.Tasks;
78

89
namespace Winton.DomainModelling.DocumentDb
@@ -32,10 +33,13 @@ public interface IEntityFacade<TEntity, in TEntityId>
3233
Task Delete(TEntityId id);
3334

3435
/// <summary>
35-
/// Query <see cref="Entity{TEntityId}" /> instances of a specified type.
36+
/// Query <see cref="Entity{TEntityId}" /> instances of a specified type. If a predicate expression is supplied, it
37+
/// will be evaluated directly by the DocumentDb query provider (database-side), so must be supported by the LINQ to
38+
/// SQL API.
3639
/// </summary>
37-
/// <returns>An <see cref="IQueryable{TEntity}" />.</returns>
38-
IQueryable<TEntity> Query();
40+
/// <param name="predicate">An optional predicate to filter the results.</param>
41+
/// <returns>An <see cref="IEnumerable{TEntity}" />.</returns>
42+
IEnumerable<TEntity> Query(Expression<Func<TEntity, bool>> predicate = null);
3943

4044
/// <summary>
4145
/// Read an <see cref="Entity{TEntityId}" /> of a specified type by ID.

src/Winton.DomainModelling.DocumentDb/IValueObjectFacade.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33

44
using System;
5-
using System.Linq;
5+
using System.Collections.Generic;
6+
using System.Linq.Expressions;
67
using System.Threading.Tasks;
78

89
namespace Winton.DomainModelling.DocumentDb
@@ -29,9 +30,11 @@ public interface IValueObjectFacade<TValueObject>
2930
Task Delete(TValueObject valueObject);
3031

3132
/// <summary>
32-
/// Query Value Objects of a specified type.
33+
/// Query Value Objects of a specified type. If a predicate expression is supplied, it will be evaluated directly by
34+
/// the DocumentDb query provider (database-side), so must be supported by the LINQ to SQL API.
3335
/// </summary>
34-
/// <returns>An <see cref="IQueryable{TValueObject}" />.</returns>
35-
IQueryable<TValueObject> Query();
36+
/// <param name="predicate">An optional predicate to filter the results.</param>
37+
/// <returns>An <see cref="IEnumerable{TValueObject}" />.</returns>
38+
IEnumerable<TValueObject> Query(Expression<Func<TValueObject, bool>> predicate = null);
3639
}
3740
}

src/Winton.DomainModelling.DocumentDb/ValueObjectFacade.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Linq;
7+
using System.Linq.Expressions;
68
using System.Threading.Tasks;
79
using Microsoft.Azure.Documents;
810
using Microsoft.Azure.Documents.Client;
@@ -53,9 +55,12 @@ public async Task Delete(TValueObject valueObject)
5355
}
5456
}
5557

56-
public IQueryable<TValueObject> Query()
58+
public IEnumerable<TValueObject> Query(Expression<Func<TValueObject, bool>> predicate = null)
5759
{
58-
return CreateValueObjectDocumentQuery().Select(x => x.ValueObject);
60+
return CreateValueObjectDocumentQuery()
61+
.Select(x => x.ValueObject)
62+
.Where(predicate ?? (x => true))
63+
.AsEnumerable();
5964
}
6065

6166
private IQueryable<ValueObjectDocument<TValueObject>> CreateValueObjectDocumentQuery()

test/Winton.DomainModelling.DocumentDb.IntegrationTests/EntityOperationTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ private async Task ShouldQueryEntitiesOfCorrectType()
174174
await Task.WhenAll(entities.Select(entityFacade.Create));
175175
await Task.WhenAll(entitiesOfDifferentType.Select(otherEntityFacade.Create));
176176

177-
IQueryable<TestEntity> queriedEntities = entityFacade.Query()
178-
.Where(e => e.Value > 1);
177+
IEnumerable<TestEntity> queriedEntities = entityFacade.Query(e => e.Value > 1);
179178

180179
queriedEntities.Should().BeEquivalentTo(
181180
new List<TestEntity>

test/Winton.DomainModelling.DocumentDb.IntegrationTests/ValueObjectOperationTests.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private async Task ShouldCreateValueObjectIfItDoesNotExist()
8787
var valueObject = new TestValueObject(1);
8888
await valueObjectFacade.Create(valueObject);
8989

90-
IQueryable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
90+
IEnumerable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
9191

9292
queriedValueObjects.Should().BeEquivalentTo(new List<TestValueObject> { valueObject });
9393
}
@@ -102,7 +102,7 @@ private async Task ShouldNotCreateAnotherValueObjectIfItAlreadyExists()
102102
await valueObjectFacade.Create(valueObject);
103103
await valueObjectFacade.Create(valueObject);
104104

105-
IQueryable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
105+
IEnumerable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
106106

107107
queriedValueObjects.Should().BeEquivalentTo(new List<TestValueObject> { valueObject });
108108
}
@@ -121,7 +121,7 @@ private async Task ShouldDeleteValueObject()
121121

122122
await valueObjectFacade.Delete(valueObject);
123123

124-
IQueryable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
124+
IEnumerable<TestValueObject> queriedValueObjects = valueObjectFacade.Query();
125125

126126
queriedValueObjects.Should().BeEmpty();
127127
}
@@ -165,8 +165,7 @@ private async Task ShouldQueryValueObjectsOfCorrectType()
165165
await Task.WhenAll(valueObjects.Select(valueObjectFacade.Create));
166166
await Task.WhenAll(valueObjectsOfDifferentType.Select(otherValueObjectFacade.Create));
167167

168-
IQueryable<TestValueObject> queriedValueObjects = valueObjectFacade.Query()
169-
.Where(vo => vo.Value > 1);
168+
IEnumerable<TestValueObject> queriedValueObjects = valueObjectFacade.Query(vo => vo.Value > 1);
170169

171170
queriedValueObjects.Should().BeEquivalentTo(
172171
new List<TestValueObject>

0 commit comments

Comments
 (0)