|
4 | 4 | using System;
|
5 | 5 | using System.Collections.Generic;
|
6 | 6 | using System.Linq;
|
| 7 | +using System.Linq.Expressions; |
7 | 8 | using System.Reflection;
|
8 | 9 | using JetBrains.Annotations;
|
9 | 10 | using Microsoft.EntityFrameworkCore.Diagnostics;
|
@@ -75,6 +76,19 @@ public DbFunction(
|
75 | 76 | methodInfo.DisplayName(), methodInfo.ReturnType.ShortDisplayName()));
|
76 | 77 | }
|
77 | 78 |
|
| 79 | + if (methodInfo.ReturnType.IsGenericType |
| 80 | + && methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(IQueryable<>)) |
| 81 | + { |
| 82 | + IsIQueryable = true; |
| 83 | + |
| 84 | + //todo - if the generic argument is not usuable as an entitytype should we throw here? IE IQueryable<int> |
| 85 | + //the built in entitytype will throw is the type is not a class |
| 86 | + if (model.FindEntityType(methodInfo.ReturnType.GetGenericArguments()[0]) == null) |
| 87 | + { |
| 88 | + model.AddEntityType(methodInfo.ReturnType.GetGenericArguments()[0]).SetAnnotation(RelationalAnnotationNames.QueryableFunctionResultType, null); |
| 89 | + } |
| 90 | + } |
| 91 | + |
78 | 92 | MethodInfo = methodInfo;
|
79 | 93 |
|
80 | 94 | _model = model;
|
@@ -310,6 +324,14 @@ public virtual Func<IReadOnlyCollection<SqlExpression>, SqlExpression> Translati
|
310 | 324 | set => SetTranslation(value, ConfigurationSource.Explicit);
|
311 | 325 | }
|
312 | 326 |
|
| 327 | + /// <summary> |
| 328 | + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to |
| 329 | + /// the same compatibility standards as public APIs. It may be changed or removed without notice in |
| 330 | + /// any release. You should only use it directly in your code with extreme caution and knowing that |
| 331 | + /// doing so can result in application failures when updating to a new Entity Framework Core release. |
| 332 | + /// </summary> |
| 333 | + public virtual bool IsIQueryable { get; } |
| 334 | + |
313 | 335 | /// <summary>
|
314 | 336 | /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
315 | 337 | /// the same compatibility standards as public APIs. It may be changed or removed without notice in
|
@@ -345,7 +367,27 @@ private void UpdateTranslationConfigurationSource(ConfigurationSource configurat
|
345 | 367 | public static DbFunction FindDbFunction(
|
346 | 368 | [NotNull] IModel model,
|
347 | 369 | [NotNull] MethodInfo methodInfo)
|
348 |
| - => model[BuildAnnotationName(methodInfo)] as DbFunction; |
| 370 | + { |
| 371 | + var dbFunction = model[BuildAnnotationName(methodInfo)] as DbFunction; |
| 372 | + |
| 373 | + if (dbFunction == null |
| 374 | + && methodInfo.GetParameters().Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition() == typeof(Expression<>))) |
| 375 | + { |
| 376 | + var parameters = methodInfo.GetParameters().Select(p => p.ParameterType.IsGenericType |
| 377 | + && p.ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) |
| 378 | + && p.ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func<>) |
| 379 | + ? p.ParameterType.GetGenericArguments()[0].GetGenericArguments()[0] |
| 380 | + : p.ParameterType).ToArray(); |
| 381 | + |
| 382 | + var nonExpressionMethod = methodInfo.DeclaringType.GetMethod(methodInfo.Name, parameters); |
| 383 | + |
| 384 | + dbFunction = nonExpressionMethod != null |
| 385 | + ? model[BuildAnnotationName(nonExpressionMethod)] as DbFunction |
| 386 | + : null; |
| 387 | + } |
| 388 | + |
| 389 | + return dbFunction; |
| 390 | + } |
349 | 391 |
|
350 | 392 | /// <summary>
|
351 | 393 | /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
|
0 commit comments