diff --git a/src/OfX.EntityFrameworkCore/EfQueryOfHandler.cs b/src/OfX.EntityFrameworkCore/EfQueryOfHandler.cs index e741184..bf03f83 100644 --- a/src/OfX.EntityFrameworkCore/EfQueryOfHandler.cs +++ b/src/OfX.EntityFrameworkCore/EfQueryOfHandler.cs @@ -4,7 +4,9 @@ using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using OfX.Abstractions; +using OfX.ApplicationModels; using OfX.Attributes; +using OfX.Cached; using OfX.EntityFrameworkCore.Delegates; using OfX.Responses; @@ -37,28 +39,25 @@ public async Task> GetDataAsync(RequestContext(data); } - // Todo: This is very first version, which is support for string. I need to define for specific type. This will be update later one! + // Currently, the Id type is supported for primitive type, in the next version. The strongly-type should be supported! + // I cannot find the way to optimize this one on this moment because seem this cannot be cached. + // Tried to use FromRawSql, but I need to write all Query like Select * from... + // Mark this one as the issue. I'll back later one! + // May I should cache the containsMethod, idAsString first! private Expression> BuildFilter(RequestOf query) { - var parameter = Expression.Parameter(typeof(TModel), "x"); - var property = Expression.Property(parameter, idPropertyName); + var modelIdData = GetModelData(); var selectorsConstant = Expression.Constant(query.SelectorIds); - var containsMethod = typeof(List).GetMethod("Contains", [typeof(string)]); - var containsCall = Expression.Call(selectorsConstant, containsMethod!, property); - return Expression.Lambda>(containsCall, parameter); + var containsCall = Expression.Call(selectorsConstant, OfXCached.IdsContainsMethodLazy.Value, + modelIdData.MethodCallExpression); + return Expression.Lambda>(containsCall, modelIdData.ParameterExpression); } private Expression> BuildResponse(RequestOf request) { return ExpressionMapModelStorage.Value.GetOrAdd(request.Expression, expression => { - var parameter = Expression.Parameter(typeof(TModel), "x"); - - // Access the Id property on the model - var idProperty = Expression.Property(parameter, idPropertyName); - var toStringMethod = typeof(object).GetMethod(nameof(ToString), Type.EmptyTypes); - var idAsString = Expression.Call(idProperty, toStringMethod!); - + var (parameter, idAsString) = GetModelData(); var expressionParts = expression.Split('.'); Expression currentExpression = parameter; var currentType = typeof(TModel); @@ -113,10 +112,8 @@ private Expression> BuildResponse(RequestOf { - Expression.Bind(typeof(OfXDataResponse).GetProperty(nameof(OfXDataResponse.Id))!, - idAsString), - Expression.Bind(typeof(OfXDataResponse).GetProperty(nameof(OfXDataResponse.Value))!, - serializeCall) + Expression.Bind(typeof(OfXDataResponse).GetProperty(nameof(OfXDataResponse.Id))!, idAsString), + Expression.Bind(typeof(OfXDataResponse).GetProperty(nameof(OfXDataResponse.Value))!, serializeCall) }; // Create a new OfXDataResponse object @@ -126,4 +123,14 @@ private Expression> BuildResponse(RequestOf>(newExpression, parameter); }); } + + private ModelIdData GetModelData() => OfXCached.ModelIdDataCachedLazy + .Value.GetOrAdd(typeof(TModel), modelType => + { + var parameter = Expression.Parameter(modelType, "x"); + var idProperty = Expression.Property(parameter, idPropertyName); + var toStringMethod = typeof(object).GetMethod(nameof(ToString), Type.EmptyTypes); + var idAsString = Expression.Call(idProperty, toStringMethod!); + return new ModelIdData(parameter, idAsString); + }); } \ No newline at end of file diff --git a/src/OfX.EntityFrameworkCore/OfX.EntityFrameworkCore.csproj b/src/OfX.EntityFrameworkCore/OfX.EntityFrameworkCore.csproj index 5b0cf39..8c0d99a 100644 --- a/src/OfX.EntityFrameworkCore/OfX.EntityFrameworkCore.csproj +++ b/src/OfX.EntityFrameworkCore/OfX.EntityFrameworkCore.csproj @@ -4,7 +4,7 @@ enable net9.0;net8.0 default - 3.0.2 + 3.0.3 Quy Vu OfX-EFCore OfX extension. Use EntityFramework as Data Querying diff --git a/src/OfX.EntityFrameworkCore/README.md b/src/OfX.EntityFrameworkCore/README.md index a9e8078..713be99 100644 --- a/src/OfX.EntityFrameworkCore/README.md +++ b/src/OfX.EntityFrameworkCore/README.md @@ -65,7 +65,7 @@ public class User ``` That all! Let go to the moon! -Note: In this release, Id is exclusively supported as a string. But hold tight—I'm gearing up to blow your mind with the next update! Stay tuned! +Note: Currently, the Id type is supported for primitive type, in the next version. The strongly-type should be supported! | Package Name | Description | .NET Version | Document | |----------------------------------------------------------|-------------------------------------------------------------------------------------------------|--------------|---------------------------------------------------------------------------| diff --git a/src/OfX.Grpc/OfX.Grpc.csproj b/src/OfX.Grpc/OfX.Grpc.csproj index ce647b1..52f8922 100644 --- a/src/OfX.Grpc/OfX.Grpc.csproj +++ b/src/OfX.Grpc/OfX.Grpc.csproj @@ -4,7 +4,7 @@ enable net9.0;net8.0 default - 3.0.2 + 3.0.3 Quy Vu OfX-gRPC OfX extension. Use gRPC as Data transporting diff --git a/src/OfX/ApplicationModels/ModelIdData.cs b/src/OfX/ApplicationModels/ModelIdData.cs new file mode 100644 index 0000000..cd2a993 --- /dev/null +++ b/src/OfX/ApplicationModels/ModelIdData.cs @@ -0,0 +1,5 @@ +using System.Linq.Expressions; + +namespace OfX.ApplicationModels; + +public sealed record ModelIdData(ParameterExpression ParameterExpression, MethodCallExpression MethodCallExpression); \ No newline at end of file diff --git a/src/OfX/Cached/OfXCached.cs b/src/OfX/Cached/OfXCached.cs index 9026e7a..0e35b42 100644 --- a/src/OfX/Cached/OfXCached.cs +++ b/src/OfX/Cached/OfXCached.cs @@ -1,5 +1,7 @@ using System.Collections.Concurrent; using System.Linq.Expressions; +using System.Reflection; +using OfX.ApplicationModels; namespace OfX.Cached; @@ -10,6 +12,11 @@ public static class OfXCached private static readonly Lazy>> ConstructorCache = new(() => []); + public static readonly Lazy IdsContainsMethodLazy = + new(() => typeof(List).GetMethod("Contains", [typeof(string)])); + + public static readonly Lazy> ModelIdDataCachedLazy = new(() => []); + public static object CreateInstanceWithCache(Type type, params object[] args) { if (ConstructorCache.Value.TryGetValue(type, out var factory)) return factory(args); diff --git a/src/OfX/OfX.csproj b/src/OfX/OfX.csproj index 093a64e..2c046c5 100644 --- a/src/OfX/OfX.csproj +++ b/src/OfX/OfX.csproj @@ -4,7 +4,7 @@ enable net9.0;net8.0 default - 3.0.2 + 3.0.3 Quy Vu OfX The high performance and easiest way to play with microservices for .NET