Skip to content

Commit 9534dd0

Browse files
committed
feat: enumeration support
1 parent 73ee083 commit 9534dd0

File tree

6 files changed

+72
-16
lines changed

6 files changed

+72
-16
lines changed

src/QueryableValues.SqlServer/EntityPropertyMapping.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,27 @@ private EntityPropertyMapping(PropertyInfo source, PropertyInfo target, Type nor
4343
Source = source;
4444
Target = target;
4545
NormalizedType = normalizedType;
46+
TypeName = GetTypeName(normalizedType);
4647

47-
if (SimpleTypes.TryGetValue(normalizedType, out EntityPropertyTypeName typeName))
48+
if (TypeName == EntityPropertyTypeName.Unknown)
4849
{
49-
TypeName = typeName;
50+
throw new NotSupportedException($"{source.PropertyType.FullName} is not supported.");
51+
}
52+
}
53+
54+
public static EntityPropertyTypeName GetTypeName(Type type)
55+
{
56+
if (SimpleTypes.TryGetValue(type, out EntityPropertyTypeName typeName))
57+
{
58+
return typeName;
5059
}
5160
else
5261
{
53-
throw new NotSupportedException($"{source.PropertyType.FullName} is not supported.");
62+
return EntityPropertyTypeName.Unknown;
5463
}
5564
}
5665

57-
private static Type GetNormalizedType(Type type) => Nullable.GetUnderlyingType(type) ?? type;
66+
public static Type GetNormalizedType(Type type) => Nullable.GetUnderlyingType(type) ?? type;
5867

5968
public static bool IsSimpleType(Type type)
6069
{

src/QueryableValues.SqlServer/EntityPropertyTypeName.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
internal enum EntityPropertyTypeName
44
{
5+
Unknown,
56
Boolean,
67
Byte,
78
Int16,

src/QueryableValues.SqlServer/IQueryableFactory.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if EFCORE
2-
using BlazarTech.QueryableValues.Builders;
1+
using BlazarTech.QueryableValues.Builders;
32
using Microsoft.EntityFrameworkCore;
43
using System;
54
using System.Collections.Generic;
@@ -21,8 +20,9 @@ internal interface IQueryableFactory
2120
IQueryable<char> Create(DbContext dbContext, IEnumerable<char> values, bool isUnicode);
2221
IQueryable<string> Create(DbContext dbContext, IEnumerable<string> values, bool isUnicode);
2322
IQueryable<Guid> Create(DbContext dbContext, IEnumerable<Guid> values);
23+
public IQueryable<TEnum> Create<TEnum>(DbContext dbContext, IEnumerable<TEnum> values)
24+
where TEnum : struct, Enum;
2425
IQueryable<TSource> Create<TSource>(DbContext dbContext, IEnumerable<TSource> values, Action<EntityOptionsBuilder<TSource>>? configure)
2526
where TSource : notnull;
2627
}
2728
}
28-
#endif

src/QueryableValues.SqlServer/QueryableValuesDbContextExtensions.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if EFCORE
2-
using BlazarTech.QueryableValues.Builders;
1+
using BlazarTech.QueryableValues.Builders;
32
using BlazarTech.QueryableValues.SqlServer;
43
using Microsoft.EntityFrameworkCore;
54
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -227,6 +226,27 @@ public static IQueryable<Guid> AsQueryableValues(this DbContext dbContext, IEnum
227226
return GetQueryableFactory(dbContext).Create(dbContext, values);
228227
}
229228

229+
/// <summary>
230+
/// Allows an <see cref="IEnumerable{Enum}">IEnumerable&lt;Enum&gt;</see> to be composed in an Entity Framework query.
231+
/// </summary>
232+
/// <remarks>
233+
/// The supported underlying types are: <see cref="byte"/>, <see cref="short"/>, <see cref="int"/>, and <see cref="long"/>.
234+
/// <para>
235+
/// More info: <see href="https://learn.microsoft.com/en-us/dotnet/api/system.enum#remarks"/>.
236+
/// </para>
237+
/// </remarks>
238+
/// <param name="dbContext">The <see cref="DbContext"/> owning the query.</param>
239+
/// <param name="values">The sequence of values to compose.</param>
240+
/// <returns>An <see cref="IQueryable{Enum}">IQueryable&lt;Enum&gt;</see> that can be composed with other entities in the query.</returns>
241+
/// <exception cref="ArgumentNullException"></exception>
242+
/// <exception cref="InvalidOperationException"></exception>
243+
public static IQueryable<TEnum> AsQueryableValues<TEnum>(this DbContext dbContext, IEnumerable<TEnum> values)
244+
where TEnum : struct, Enum
245+
{
246+
ValidateParameters(dbContext, values);
247+
return GetQueryableFactory(dbContext).Create(dbContext, values);
248+
}
249+
230250
/// <summary>
231251
/// Allows an <see cref="IEnumerable{T}"/> to be composed in an Entity Framework query.
232252
/// </summary>
@@ -244,4 +264,3 @@ public static IQueryable<TSource> AsQueryableValues<TSource>(this DbContext dbCo
244264
}
245265
}
246266
}
247-
#endif

src/QueryableValues.SqlServer/QueryableValuesEnabledDbContextExtensions.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if EFCORE
2-
using BlazarTech.QueryableValues.Builders;
1+
using BlazarTech.QueryableValues.Builders;
32
using Microsoft.EntityFrameworkCore;
43
using System;
54
using System.Collections.Generic;
@@ -200,6 +199,21 @@ public static IQueryable<Guid> AsQueryableValues(this IQueryableValuesEnabledDbC
200199
return GetDbContext(dbContext).AsQueryableValues(values);
201200
}
202201

202+
/// <summary>
203+
/// <inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TEnum}(DbContext, IEnumerable{TEnum})"/>
204+
/// </summary>
205+
/// <param name="dbContext"><inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TEnum}(DbContext, IEnumerable{TEnum})" path="/param[@name='dbContext']"/></param>
206+
/// <param name="values"><inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TEnum}(DbContext, IEnumerable{TEnum})" path="/param[@name='values']"/></param>
207+
/// <returns><inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TEnum}(DbContext, IEnumerable{TEnum})"/></returns>
208+
/// <remarks><inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TEnum}(DbContext, IEnumerable{TEnum})"/></remarks>
209+
/// <exception cref="ArgumentNullException"></exception>
210+
/// <exception cref="InvalidOperationException"></exception>
211+
public static IQueryable<TEnum> AsQueryableValues<TEnum>(this IQueryableValuesEnabledDbContext dbContext, IEnumerable<TEnum> values)
212+
where TEnum : struct, Enum
213+
{
214+
return GetDbContext(dbContext).AsQueryableValues(values);
215+
}
216+
203217
/// <summary>
204218
/// <inheritdoc cref="QueryableValuesDbContextExtensions.AsQueryableValues{TSource}(DbContext, IEnumerable{TSource}, Action{EntityOptionsBuilder{TSource}}?)"/>
205219
/// </summary>
@@ -217,4 +231,3 @@ public static IQueryable<TSource> AsQueryableValues<TSource>(this IQueryableValu
217231
}
218232
}
219233
}
220-
#endif

src/QueryableValues.SqlServer/SqlServer/QueryableFactory.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
#if EFCORE
2-
using BlazarTech.QueryableValues.Builders;
1+
using BlazarTech.QueryableValues.Builders;
32
using BlazarTech.QueryableValues.Serializers;
43
using Microsoft.Data.SqlClient;
54
using Microsoft.EntityFrameworkCore;
@@ -387,6 +386,22 @@ public IQueryable<Guid> Create(DbContext dbContext, IEnumerable<Guid> values)
387386
return CreateForSimpleType(dbContext, values);
388387
}
389388

389+
public IQueryable<TEnum> Create<TEnum>(DbContext dbContext, IEnumerable<TEnum> values)
390+
where TEnum : struct, Enum
391+
{
392+
var enumType = typeof(TEnum);
393+
var normalizedType = EntityPropertyMapping.GetNormalizedType(Enum.GetUnderlyingType(enumType));
394+
395+
return EntityPropertyMapping.GetTypeName(normalizedType) switch
396+
{
397+
EntityPropertyTypeName.Int32 => CreateForSimpleType(dbContext, values.Select(i => (int)(object)i)).Select(i => (TEnum)(object)i),
398+
EntityPropertyTypeName.Byte => CreateForSimpleType(dbContext, values.Select(i => (byte)(object)i)).Select(i => (TEnum)(object)i),
399+
EntityPropertyTypeName.Int16 => CreateForSimpleType(dbContext, values.Select(i => (short)(object)i)).Select(i => (TEnum)(object)i),
400+
EntityPropertyTypeName.Int64 => CreateForSimpleType(dbContext, values.Select(i => (long)(object)i)).Select(i => (TEnum)(object)i),
401+
_ => throw new NotSupportedException($"The underlying type of {enumType.FullName} ({normalizedType.FullName}) is not supported.")
402+
};
403+
}
404+
390405
public IQueryable<TSource> Create<TSource>(DbContext dbContext, IEnumerable<TSource> values, Action<EntityOptionsBuilder<TSource>>? configure)
391406
where TSource : notnull
392407
{
@@ -470,4 +485,3 @@ public IQueryable<TSource> Create<TSource>(DbContext dbContext, IEnumerable<TSou
470485
}
471486
}
472487
}
473-
#endif

0 commit comments

Comments
 (0)