Skip to content

Commit c93ea29

Browse files
Ihar YakimushIhar Yakimush
authored andcommitted
support Select method
1 parent a06d990 commit c93ea29

File tree

14 files changed

+300
-85
lines changed

14 files changed

+300
-85
lines changed

SolrNet.IntegrationOData/Controllers/ValuesController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public IActionResult Get()
3838
[HttpGet("{id}")]
3939
public ActionResult<string> Get(int id, ODataQueryOptions odata)
4040
{
41-
SolrQuery<Product> query = this.Solr.AsQueryable(options =>
41+
IQueryable<Product> query = this.Solr.AsQueryable(options =>
4242
{
4343
// Set q parameter. By default *:* will be used
4444
options.MainQuery = new SolrQuery("*:*");

SolrNet.Linq.IntegrationTests/EnumeratedTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public async Task Any()
120120
public async Task CountLongCount()
121121
{
122122
var c1 = await Product.SolrOperations.Value.AsQueryable().CountAsync(p => p.Id != "qwe");
123-
var c2 = await Product.SolrOperations.Value.AsQueryable().LongCountAsync(p => p.Id != "qwe");
123+
long c2 = await Product.SolrOperations.Value.AsQueryable().LongCountAsync(p => p.Id != "qwe");
124124
var c3 = Product.SolrOperations.Value.AsQueryable().LongCount(p => p.Id != "qwe");
125125
var c4 = Product.SolrOperations.Value.AsQueryable().Count(p => p.Id != "qwe");
126126

@@ -134,10 +134,10 @@ public async Task CountLongCount()
134134
var c7 = Product.SolrOperations.Value.AsQueryable().LongCount(p => p.Id == "qwe");
135135
var c8 = Product.SolrOperations.Value.AsQueryable().Count(p => p.Id == "qwe");
136136

137-
Assert.Equal(0, c1);
138-
Assert.Equal(0, c2);
139-
Assert.Equal(0, c3);
140-
Assert.Equal(0, c4);
137+
Assert.Equal(0, c5);
138+
Assert.Equal(0, c6);
139+
Assert.Equal(0, c7);
140+
Assert.Equal(0, c8);
141141
}
142142
}
143143
}
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
23
using Xunit;
34

45
namespace SolrNet.Linq.IntegrationTests
56
{
67
public class SelectTests
78
{
8-
//[Fact]
9-
//public void AnonimousClass()
10-
//{
11-
// var t1 = Product.SolrOperations.Value.AsQueryable().Select(p => new {p.Id, p.Price}).AsEnumerable()
12-
// .FirstOrDefault();
9+
[Fact]
10+
public void AnonymousClass()
11+
{
12+
var t1 = Product.SolrOperations.Value.AsQueryable().Where(p => p.Id != null)
13+
.Select(p => new {p.Id, p.Price, p.Categories, Qwe = Math.Pow(2,2) })
14+
.Where(arg => arg.Categories.Any(s => s == "electronics"))
15+
.OrderBy(arg => arg.Id)
16+
.FirstOrDefault();
1317

14-
// Assert.NotNull(t1);
15-
//}
18+
Assert.NotNull(t1);
19+
}
1620
}
1721
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq.Expressions;
4+
using System.Reflection;
5+
6+
namespace SolrNet.Linq.Expressions.Context
7+
{
8+
public class SelectContext : MemberContext
9+
{
10+
public NewExpression Expression { get; }
11+
public MemberContext ParentContext { get; }
12+
13+
public Dictionary<MemberInfo, string> Members { get; } = new Dictionary<MemberInfo, string>();
14+
public Dictionary<MemberInfo, string> Aliases { get; } = new Dictionary<MemberInfo, string>();
15+
16+
public SelectContext(NewExpression expression, MemberContext parentContext)
17+
{
18+
Expression = expression ?? throw new ArgumentNullException(nameof(expression));
19+
ParentContext = parentContext ?? throw new ArgumentNullException(nameof(parentContext));
20+
21+
for (int i = 0; i < expression.Arguments.Count; i++)
22+
{
23+
Expression argument = expression.Arguments[i];
24+
if (argument.NodeType != ExpressionType.MemberAccess)
25+
{
26+
string value = $"v{i}:{parentContext.GetSolrMemberProduct(argument)}";
27+
Aliases.Add(expression.Members[i], value);
28+
}
29+
else
30+
{
31+
Members.Add(expression.Members[i], parentContext.GetSolrMemberProduct(argument, true));
32+
}
33+
}
34+
}
35+
public override bool HasMemberAccess(Expression expression)
36+
{
37+
throw new System.NotImplementedException();
38+
}
39+
40+
public override string GetSolrMemberProduct(Expression expression, bool disableFunctions = false)
41+
{
42+
throw new System.NotImplementedException();
43+
}
44+
45+
public override bool IsAccessToMember(MemberExpression expression)
46+
{
47+
return Members.ContainsKey(expression.Member);
48+
}
49+
}
50+
}

SolrNet.Linq/Expressions/EnumerateMethod.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static EnumeratedResult TryVisitEnumerate(this MethodCallExpression node,
4747
}
4848
if (node.Method.Name == LongCount)
4949
{
50-
result = EnumeratedResult.Count;
50+
result = EnumeratedResult.LongCount;
5151
}
5252

5353
if (node.Method.DeclaringType == typeof(Queryable) && result != EnumeratedResult.None)
@@ -77,7 +77,7 @@ public static EnumeratedResult TryVisitEnumerate(this MethodCallExpression node,
7777
options.Rows = 1;
7878
}
7979

80-
if (result == EnumeratedResult.Any || result == EnumeratedResult.Count)
80+
if (result == EnumeratedResult.Any || result == EnumeratedResult.Count || result == EnumeratedResult.LongCount)
8181
{
8282
options.Rows = 0;
8383
}

SolrNet.Linq/Expressions/EnumeratedResult.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public enum EnumeratedResult
88
Single = 3,
99
SingleOrDefault = 4,
1010
Any = 5,
11-
Count = 6
11+
Count = 6,
12+
LongCount = 7
1213
}
1314
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Linq.Expressions;
5+
using System.Reflection;
6+
using SolrNet.Commands.Parameters;
7+
using SolrNet.Linq.Expressions.Context;
8+
9+
namespace SolrNet.Linq.Expressions.NodeTypeHelpers
10+
{
11+
public static class SelectMethod
12+
{
13+
public const string Select = nameof(Queryable.Select);
14+
public static bool TryVisitSelect(this MethodCallExpression node, QueryOptions options, MemberContext context, out SelectContext newContext)
15+
{
16+
newContext = null;
17+
bool result = node.Method.DeclaringType == typeof(Queryable) && node.Method.Name == Select;
18+
if (result)
19+
{
20+
Expression arg = node.Arguments[1];
21+
22+
if (arg.NodeType == ExpressionType.Quote)
23+
{
24+
LambdaExpression lambda = (LambdaExpression)node.Arguments[1].StripQuotes();
25+
26+
if (lambda.Body is NewExpression selectMember)
27+
{
28+
newContext = new SelectContext(selectMember, context);
29+
30+
foreach (var pairValue in newContext.Aliases.Values.Concat(newContext.Members.Values))
31+
{
32+
options.Fields.Add(pairValue);
33+
}
34+
35+
return result;
36+
}
37+
}
38+
39+
throw new InvalidOperationException($"Unable to translate '{Select}' method.");
40+
}
41+
42+
return result;
43+
}
44+
}
45+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Linq.Expressions;
3+
using SolrNet.Linq.Expressions.Context;
4+
5+
namespace SolrNet.Linq.Expressions
6+
{
7+
public class SelectQueryProvider<TEntity,TDocument> : SolrQueryProvider<TEntity, TDocument>
8+
{
9+
public SelectQueryProvider(ISolrBasicReadOnlyOperations<TDocument> operations, SolrNetLinqOptions options,
10+
MethodCallExpression selectExpression, MemberContext context) : base(operations, options, context)
11+
{
12+
}
13+
14+
protected override TEntity GetEntity(TDocument document)
15+
{
16+
throw new NotImplementedException();
17+
}
18+
}
19+
}

SolrNet.Linq/IAsyncProvider.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Linq.Expressions;
2+
using System.Threading.Tasks;
3+
4+
namespace SolrNet.Linq
5+
{
6+
public interface IAsyncProvider<TEntity>
7+
{
8+
Task<TResult> ExecuteAsync<TResult>(Expression expression);
9+
}
10+
}

SolrNet.Linq/SolrLinqExtensions.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ namespace SolrNet.Linq
1010
public static class SolrLinqExtensions
1111
{
1212
public static async Task<long> LongCountAsync<TSource>(this IQueryable<TSource> query)
13-
{
14-
return await query.CountAsync();
13+
{
14+
int countAsync = await query.CountAsync();
15+
return (long)countAsync;
1516
}
1617

1718
public static async Task<long> LongCountAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
1819
{
19-
return await query.LongCountAsync();
20+
return await query.Where(predicate).LongCountAsync();
2021
}
2122

2223
public static async Task<int> CountAsync<TSource>(this IQueryable<TSource> query)
2324
{
24-
if (query.Provider is SolrQueryProvider<TSource> provider)
25+
if (query.Provider is IAsyncProvider<TSource> provider)
2526
{
2627
MethodCallExpression mce = Expression.Call(
2728
null,
@@ -38,11 +39,11 @@ public static async Task<int> CountAsync<TSource>(this IQueryable<TSource> query
3839

3940
public static async Task<int> CountAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
4041
{
41-
if (query.Provider is SolrQueryProvider<TSource> provider)
42+
if (query.Provider is IAsyncProvider<TSource> provider)
4243
{
4344
var result = await provider.ExecuteAsync<int>(Expression.Call(
4445
null,
45-
GetMethod<TSource>(nameof(Queryable.Any), 2), query.Expression, predicate));
46+
GetMethod<TSource>(nameof(Queryable.Count), 2), query.Expression, predicate));
4647

4748
return result;
4849
}
@@ -52,7 +53,7 @@ public static async Task<int> CountAsync<TSource>(this IQueryable<TSource> query
5253

5354
public static async Task<bool> AnyAsync<TSource>(this IQueryable<TSource> query)
5455
{
55-
if (query.Provider is SolrQueryProvider<TSource> provider)
56+
if (query.Provider is IAsyncProvider<TSource> provider)
5657
{
5758
MethodCallExpression mce = Expression.Call(
5859
null,
@@ -69,7 +70,7 @@ public static async Task<bool> AnyAsync<TSource>(this IQueryable<TSource> query)
6970

7071
public static async Task<bool> AnyAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
7172
{
72-
if (query.Provider is SolrQueryProvider<TSource> provider)
73+
if (query.Provider is IAsyncProvider<TSource> provider)
7374
{
7475
bool result = await provider.ExecuteAsync<bool>(Expression.Call(
7576
null,
@@ -83,7 +84,7 @@ public static async Task<bool> AnyAsync<TSource>(this IQueryable<TSource> query,
8384

8485
public static async Task<TSource> FirstAsync<TSource>(this IQueryable<TSource> query)
8586
{
86-
if (query.Provider is SolrQueryProvider<TSource> provider)
87+
if (query.Provider is IAsyncProvider<TSource> provider)
8788
{
8889
MethodCallExpression mce = Expression.Call(
8990
null,
@@ -100,7 +101,7 @@ public static async Task<TSource> FirstAsync<TSource>(this IQueryable<TSource> q
100101

101102
public static async Task<TSource> FirstAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
102103
{
103-
if (query.Provider is SolrQueryProvider<TSource> provider)
104+
if (query.Provider is IAsyncProvider<TSource> provider)
104105
{
105106
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
106107
null,
@@ -114,7 +115,7 @@ public static async Task<TSource> FirstAsync<TSource>(this IQueryable<TSource> q
114115

115116
public static async Task<TSource> FirstOrDefaultAsync<TSource>(this IQueryable<TSource> query)
116117
{
117-
if (query.Provider is SolrQueryProvider<TSource> provider)
118+
if (query.Provider is IAsyncProvider<TSource> provider)
118119
{
119120
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
120121
null,
@@ -128,7 +129,7 @@ public static async Task<TSource> FirstOrDefaultAsync<TSource>(this IQueryable<T
128129

129130
public static async Task<TSource> FirstOrDefaultAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
130131
{
131-
if (query.Provider is SolrQueryProvider<TSource> provider)
132+
if (query.Provider is IAsyncProvider<TSource> provider)
132133
{
133134
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
134135
null,
@@ -142,7 +143,7 @@ public static async Task<TSource> FirstOrDefaultAsync<TSource>(this IQueryable<T
142143

143144
public static async Task<TSource> SingleAsync<TSource>(this IQueryable<TSource> query)
144145
{
145-
if (query.Provider is SolrQueryProvider<TSource> provider)
146+
if (query.Provider is IAsyncProvider<TSource> provider)
146147
{
147148
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
148149
null,
@@ -156,7 +157,7 @@ public static async Task<TSource> SingleAsync<TSource>(this IQueryable<TSource>
156157

157158
public static async Task<TSource> SingleAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
158159
{
159-
if (query.Provider is SolrQueryProvider<TSource> provider)
160+
if (query.Provider is IAsyncProvider<TSource> provider)
160161
{
161162
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
162163
null,
@@ -170,7 +171,7 @@ public static async Task<TSource> SingleAsync<TSource>(this IQueryable<TSource>
170171

171172
public static async Task<TSource> SingleOrDefaultAsync<TSource>(this IQueryable<TSource> query)
172173
{
173-
if (query.Provider is SolrQueryProvider<TSource> provider)
174+
if (query.Provider is IAsyncProvider<TSource> provider)
174175
{
175176
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
176177
null,
@@ -184,7 +185,7 @@ public static async Task<TSource> SingleOrDefaultAsync<TSource>(this IQueryable<
184185

185186
public static async Task<TSource> SingleOrDefaultAsync<TSource>(this IQueryable<TSource> query, Expression<Func<TSource, bool>> predicate)
186187
{
187-
if (query.Provider is SolrQueryProvider<TSource> provider)
188+
if (query.Provider is IAsyncProvider<TSource> provider)
188189
{
189190
TSource result = await provider.ExecuteAsync<TSource>(Expression.Call(
190191
null,

0 commit comments

Comments
 (0)