diff --git a/README.md b/README.md index 590fd0e3..4d89bc14 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The following frameworks are supported: - net45 and up - netstandard1.3 - netstandard2.0 -- uap10.0 +- uap10.0 (TODO...)s ## Fork details This fork takes the basic library to a new level. Contains XML Documentation and examples on how to use it. Also adds unit testing to help ensure that it works properly. diff --git a/System.Linq.Dynamic.Core.sln b/System.Linq.Dynamic.Core.sln index 4bd30725..c1195933 100644 --- a/System.Linq.Dynamic.Core.sln +++ b/System.Linq.Dynamic.Core.sln @@ -53,6 +53,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp_netcore2.0_EF2.0 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemoryLeakTest167", "src-console\MemoryLeakTest167\MemoryLeakTest167.csproj", "{AD4F83E5-4240-485D-BB5C-F43974F716E4}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp_netcore2.0_EF2.1", "src-console\ConsoleAppEF2.1\ConsoleApp_netcore2.0_EF2.1.csproj", "{EDF434F6-70C0-4005-B63E-0C365B3DA42A}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp_netcore2.1_EF2.1.1_InMemory", "src-console\ConsoleAppEF2.1.1_InMemory\ConsoleApp_netcore2.1_EF2.1.1_InMemory.csproj", "{E4286D1D-A98C-4516-9E47-CBF9739448DA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp_netcore2.1_EF2.1.1", "src-console\ConsoleAppEF2.1.1\ConsoleApp_netcore2.1_EF2.1.1.csproj", "{F1880F07-238F-4A3A-9E58-141350665E1F}" @@ -291,6 +293,22 @@ Global {AD4F83E5-4240-485D-BB5C-F43974F716E4}.Release|x64.Build.0 = Release|Any CPU {AD4F83E5-4240-485D-BB5C-F43974F716E4}.Release|x86.ActiveCfg = Release|Any CPU {AD4F83E5-4240-485D-BB5C-F43974F716E4}.Release|x86.Build.0 = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|ARM.Build.0 = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|x64.ActiveCfg = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|x64.Build.0 = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|x86.ActiveCfg = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Debug|x86.Build.0 = Debug|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|Any CPU.Build.0 = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|ARM.ActiveCfg = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|ARM.Build.0 = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|x64.ActiveCfg = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|x64.Build.0 = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|x86.ActiveCfg = Release|Any CPU + {EDF434F6-70C0-4005-B63E-0C365B3DA42A}.Release|x86.Build.0 = Release|Any CPU {E4286D1D-A98C-4516-9E47-CBF9739448DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4286D1D-A98C-4516-9E47-CBF9739448DA}.Debug|Any CPU.Build.0 = Debug|Any CPU {E4286D1D-A98C-4516-9E47-CBF9739448DA}.Debug|ARM.ActiveCfg = Debug|Any CPU @@ -342,6 +360,7 @@ Global {5DC68E83-ABE0-4887-B17E-1ED4EEE89C2C} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} {437473EE-7FBB-4C28-96EC-41E1AEE161F3} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} {AD4F83E5-4240-485D-BB5C-F43974F716E4} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} + {EDF434F6-70C0-4005-B63E-0C365B3DA42A} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} {E4286D1D-A98C-4516-9E47-CBF9739448DA} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} {F1880F07-238F-4A3A-9E58-141350665E1F} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} EndGlobalSection diff --git a/src-console/ConsoleAppEF2.1.1/Program.cs b/src-console/ConsoleAppEF2.1.1/Program.cs index 37803140..ff0e7adc 100644 --- a/src-console/ConsoleAppEF2.1.1/Program.cs +++ b/src-console/ConsoleAppEF2.1.1/Program.cs @@ -61,7 +61,7 @@ static void Main(string[] args) }; Console.WriteLine("all {0}", JsonConvert.SerializeObject(all, Formatting.Indented)); - var config = new ParsingConfig(); + var config = ParsingConfig.DefaultEFCore21; config.CustomTypeProvider = new C(); var context = new TestContext(); @@ -79,8 +79,11 @@ static void Main(string[] args) context.SaveChanges(); } - var carFirstOrDefault = context.Cars.Where(config, "Brand == \"Ford\""); - Console.WriteLine("carFirstOrDefault {0}", JsonConvert.SerializeObject(carFirstOrDefault, Formatting.Indented)); + var carFirstOrDefault1 = context.Cars.Where(config, "Brand == \"Ford\""); + Console.WriteLine("carFirstOrDefault1 {0}", JsonConvert.SerializeObject(carFirstOrDefault1, Formatting.Indented)); + + var carFirstOrDefault2 = context.Cars.Where(config, "Brand == @0", "Alfa"); + Console.WriteLine("carFirstOrDefault2 {0}", JsonConvert.SerializeObject(carFirstOrDefault2, Formatting.Indented)); var carsLike1 = from c in context.Cars diff --git a/src-console/ConsoleAppEF2.1/ConsoleApp_netcore2.0_EF2.1.csproj b/src-console/ConsoleAppEF2.1/ConsoleApp_netcore2.0_EF2.1.csproj new file mode 100644 index 00000000..4351e79f --- /dev/null +++ b/src-console/ConsoleAppEF2.1/ConsoleApp_netcore2.0_EF2.1.csproj @@ -0,0 +1,21 @@ + + + + Exe + netcoreapp2.0 + ConsoleAppEF21 + ConsoleAppEF21 + + + + + + + + + + + + + + diff --git a/src-console/ConsoleAppEF2.1/Database/Car.cs b/src-console/ConsoleAppEF2.1/Database/Car.cs new file mode 100644 index 00000000..3c16220e --- /dev/null +++ b/src-console/ConsoleAppEF2.1/Database/Car.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; + +namespace ConsoleAppEF21.Database +{ + public class Car + { + [Key] + public int Key { get; set; } + + [Required] + [StringLength(8)] + public string Vin { get; set; } + + [Required] + public string Year { get; set; } + + [Required] + public string Brand { get; set; } + + [Required] + public string Color { get; set; } + } +} diff --git a/src-console/ConsoleAppEF2.1/Database/TestContext.cs b/src-console/ConsoleAppEF2.1/Database/TestContext.cs new file mode 100644 index 00000000..e15488fe --- /dev/null +++ b/src-console/ConsoleAppEF2.1/Database/TestContext.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; + +namespace ConsoleAppEF21.Database +{ + public class TestContext : DbContext + { + public static readonly LoggerFactory MyLoggerFactory = new LoggerFactory(new[] { new ConsoleLoggerProvider((filter, includeScopes) => true, true) }); + + public virtual DbSet Cars { get; set; } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseLoggerFactory(MyLoggerFactory); // Warning: Do not create a new ILoggerFactory instance each time + optionsBuilder.EnableSensitiveDataLogging(); + + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=CarsEF20;Trusted_Connection=True;"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().HasKey(c => c.Key); + } + + // https://stackoverflow.com/questions/46212704/how-do-i-write-ef-functions-extension-method + public static bool Like(string matchExpression, string pattern) => EF.Functions.Like(matchExpression, pattern); + } +} diff --git a/src-console/ConsoleAppEF2.1/Program.cs b/src-console/ConsoleAppEF2.1/Program.cs new file mode 100644 index 00000000..9c6290a5 --- /dev/null +++ b/src-console/ConsoleAppEF2.1/Program.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using ConsoleAppEF21.Database; +using Newtonsoft.Json; + +namespace ConsoleAppEF21 +{ + class Program + { + //class C : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider + //{ + // public HashSet GetCustomTypes() + // { + // var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + // var set = new HashSet(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies)) + // { + // typeof(TestContext) + // }; + + // return set; + // } + //} + + //private static IQueryable GetQueryable() + //{ + // var random = new Random((int)DateTime.Now.Ticks); + + // var x = Enumerable.Range(0, 10).Select(i => new + // { + // Id = i, + // Value = random.Next(), + // }); + + // return x.AsQueryable().Select("new (it as Id, @0 as Value)", random.Next()); + // // return x.AsQueryable(); //x.AsQueryable().Select("new (Id, Value)"); + //} + + static void Main(string[] args) + { + var list = new List { new Car { Key = 1 }, new Car { Key = 2 } }; + + var carsTest = list.AsQueryable().Where("Key = @0", "1").ToList(); + + //IQueryable qry = GetQueryable(); + + //var result = qry.Select("it").OrderBy("Value"); + //try + //{ + // Console.WriteLine("result {0}", JsonConvert.SerializeObject(result, Formatting.Indented)); + //} + //catch (Exception) + //{ + // // Console.WriteLine(e); + //} + + //var all = new + //{ + // test1 = new List { 1, 2, 3 }.ToDynamicList(typeof(int)), + // test2 = new List { 4, 5, 6 }.ToDynamicList(typeof(int)), + // test3 = new List { 7, 8, 9 }.ToDynamicList(typeof(int)) + //}; + // Console.WriteLine("all {0}", JsonConvert.SerializeObject(all, Formatting.None)); + + var config = ParsingConfig.DefaultEFCore21; + + var context = new TestContext(); + if (!context.Cars.Any()) + { + context.Cars.Add(new Car { Brand = "Ford", Color = "Blue", Vin = "yes", Year = "2017" }); + context.Cars.Add(new Car { Brand = "Fiat", Color = "Red", Vin = "yes", Year = "2016" }); + context.Cars.Add(new Car { Brand = "Alfa", Color = "Black", Vin = "no", Year = "1979" }); + context.Cars.Add(new Car { Brand = "Alfa", Color = "Black", Vin = "a%bc", Year = "1979" }); + context.SaveChanges(); + } + + //var g1 = context.Cars.GroupBy("new(Brand)").Select("new(Key.Brand as KeyValue1, it.Count() as CountValue1)").ToDynamicList(); + //Console.WriteLine("GroupBy @ local {0}", JsonConvert.SerializeObject(g1, Formatting.Indented)); + + //Console.WriteLine(new string('_', 80)); + + var g2 = context.Cars.GroupBy("new(Brand)", config).Select("new(Key.Brand as KeyValue2, it.Count() as CountValue2)").ToDynamicList(); + Console.WriteLine("GroupBy @ database {0}", JsonConvert.SerializeObject(g2, Formatting.Indented)); + + //var carFirstOrDefault = context.Cars.Where(config, "Brand == \"Ford\""); + //Console.WriteLine("carFirstOrDefault {0}", JsonConvert.SerializeObject(carFirstOrDefault, Formatting.Indented)); + + //var carsLike1 = + // from c in context.Cars + // where EF.Functions.Like(c.Brand, "%a%") + // select c; + //Console.WriteLine("carsLike1 {0}", JsonConvert.SerializeObject(carsLike1, Formatting.Indented)); + + //var cars2Like = context.Cars.Where(c => EF.Functions.Like(c.Brand, "%a%")); + //Console.WriteLine("cars2Like {0}", JsonConvert.SerializeObject(cars2Like, Formatting.Indented)); + + //var dynamicCarsLike1 = context.Cars.Where(config, "TestContext.Like(Brand, \"%a%\")"); + //Console.WriteLine("dynamicCarsLike1 {0}", JsonConvert.SerializeObject(dynamicCarsLike1, Formatting.Indented)); + + //var dynamicCarsLike2 = context.Cars.Where(config, "TestContext.Like(Brand, \"%d%\")"); + //Console.WriteLine("dynamicCarsLike2 {0}", JsonConvert.SerializeObject(dynamicCarsLike2, Formatting.Indented)); + + //var dynamicFunctionsLike1 = context.Cars.Where(config, "DynamicFunctions.Like(Brand, \"%a%\")"); + //Console.WriteLine("dynamicFunctionsLike1 {0}", JsonConvert.SerializeObject(dynamicFunctionsLike1, Formatting.Indented)); + + //var dynamicFunctionsLike2 = context.Cars.Where(config, "DynamicFunctions.Like(Vin, \"%a.%b%\", \".\")"); + //Console.WriteLine("dynamicFunctionsLike2 {0}", JsonConvert.SerializeObject(dynamicFunctionsLike2, Formatting.Indented)); + + //var testDynamic = context.Cars.Select(c => new + //{ + // K = c.Key, + // C = c.Color + //}); + + //var testDynamicResult = testDynamic.Select("it").OrderBy("C"); + //try + //{ + // Console.WriteLine("resultX {0}", JsonConvert.SerializeObject(testDynamicResult, Formatting.Indented)); + //} + //catch (Exception e) + //{ + // Console.WriteLine(e); + //} + } + } +} diff --git a/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj b/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj index 7bd63183..645f30d3 100644 --- a/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj +++ b/src/EntityFramework.DynamicLinq/EntityFramework.DynamicLinq.csproj @@ -12,7 +12,7 @@ true true system;linq;dynamic;entityframework;core;async - Bugfixes and new Features. For details see the release notes. + Bugfixes and new Features. For details see CHANGELOG.md https://github.com/StefH/System.Linq.Dynamic.Core https://github.com/StefH/System.Linq.Dynamic.Core/blob/master/licence.txt git @@ -57,4 +57,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj b/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj index 96a712fd..a2db2456 100644 --- a/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj +++ b/src/Microsoft.EntityFrameworkCore.DynamicLinq/Microsoft.EntityFrameworkCore.DynamicLinq.csproj @@ -12,7 +12,7 @@ true true system;linq;dynamic;entityframework;core;async - Bugfixes and new Features. For details see the release notes. + Bugfixes and new Features. For details see CHANGELOG.md https://github.com/StefH/System.Linq.Dynamic.Core https://github.com/StefH/System.Linq.Dynamic.Core/blob/master/licence.txt git diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs index dcf0521d..ed001349 100644 --- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs +++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs @@ -500,7 +500,7 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [CanBeNull] P Check.NotEmpty(keySelector, nameof(keySelector)); Check.NotEmpty(resultSelector, nameof(resultSelector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args); LambdaExpression elementLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, resultSelector, args); @@ -570,7 +570,7 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [CanBeNull] P Check.NotNull(source, nameof(source)); Check.NotEmpty(keySelector, nameof(keySelector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression keyLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, keySelector, args); var optimized = OptimizeExpression(Expression.Call( @@ -586,7 +586,6 @@ public static IQueryable GroupBy([NotNull] this IQueryable source, [NotNull] str { return GroupBy(source, (ParsingConfig)null, keySelector, args); } - #endregion GroupBy #region GroupByMany @@ -897,7 +896,7 @@ public static dynamic LastOrDefault([NotNull] this IQueryable source) #if NET35 public static object LastOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) #else - public static dynamic LastOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) + public static dynamic LastOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) #endif { Check.NotNull(source, nameof(source)); @@ -1134,7 +1133,7 @@ public static IQueryable Select([NotNull] this IQueryable source, [CanBeNull] Pa Check.NotNull(source, nameof(source)); Check.NotEmpty(selector, nameof(selector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, selector, args); var optimized = OptimizeExpression(Expression.Call( @@ -1174,7 +1173,7 @@ public static IQueryable Select([NotNull] this IQueryable sour Check.NotNull(source, nameof(source)); Check.NotEmpty(selector, nameof(selector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, typeof(TResult), selector, args); var optimized = OptimizeExpression(Expression.Call( @@ -1212,7 +1211,7 @@ public static IQueryable Select([NotNull] this IQueryable source, [CanBeNull] Pa Check.NotNull(resultType, nameof(resultType)); Check.NotEmpty(selector, nameof(selector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, resultType, selector, args); var optimized = OptimizeExpression(Expression.Call( @@ -1290,7 +1289,7 @@ public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] private static IQueryable SelectManyInternal(IQueryable source, ParsingConfig config, Type resultType, string selector, params object[] args) { - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, selector, args); //Extra help to get SelectMany to work from StackOverflow Answer @@ -1347,7 +1346,7 @@ public static IQueryable SelectMany([NotNull] this IQueryable Check.NotNull(source, nameof(source)); Check.NotEmpty(selector, nameof(selector)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(createParameterCtor, source.ElementType, null, selector, args); //we have to adjust to lambda to return an IEnumerable instead of whatever the actual property is. @@ -1440,7 +1439,7 @@ public static IQueryable SelectMany([NotNull] this IQueryable source, [CanBeNull Check.NotEmpty(resultSelector, nameof(resultSelector)); Check.NotEmpty(resultParameterName, nameof(resultParameterName)); - bool createParameterCtor = source.IsLinqToObjects(); + bool createParameterCtor = config?.EvaluateGroupByAtDatabase ?? source.IsLinqToObjects(); LambdaExpression sourceSelectLambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, collectionSelector, collectionSelectorArgs); //we have to adjust to lambda to return an IEnumerable instead of whatever the actual property is. @@ -1580,7 +1579,7 @@ public static dynamic SingleOrDefault([NotNull] this IQueryable source) #if NET35 public static object SingleOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) #else - public static dynamic SingleOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) + public static dynamic SingleOrDefault([NotNull] this IQueryable source, [CanBeNull] ParsingConfig config, [NotNull] string predicate, params object[] args) #endif { Check.NotNull(source, nameof(source)); diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs index 01a13c88..cc0414a5 100644 --- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs +++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs @@ -7,7 +7,18 @@ namespace System.Linq.Dynamic.Core /// public class ParsingConfig { - internal static ParsingConfig Default { get; } = new ParsingConfig(); + /// + /// Default ParsingConfig + /// + public static ParsingConfig Default { get; } = new ParsingConfig(); + + /// + /// Default ParsingConfig for EntityFramework Core 2.1 and higher + /// + public static ParsingConfig DefaultEFCore21 { get; } = new ParsingConfig + { + EvaluateGroupByAtDatabase = true + }; private IDynamicLinkCustomTypeProvider _customTypeProvider; @@ -44,9 +55,12 @@ public IDynamicLinkCustomTypeProvider CustomTypeProvider /// /// Gets or sets a value indicating whether to use dynamic object class for anonymous types. /// - /// - /// true if wether to use dynamic object class for anonymous types; otherwise, false. - /// public bool UseDynamicObjectClassForAnonymousTypes { get; set; } + + /// + /// Gets or sets a value indicating whether the EntityFramwwork version supports evaluating GroupBy at database level. + /// See https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.1#linq-groupby-translation + /// + public bool EvaluateGroupByAtDatabase { get; set; } } } diff --git a/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj b/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj index 05d8bb02..6eb8a518 100644 --- a/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj +++ b/src/System.Linq.Dynamic.Core/System.Linq.Dynamic.Core.csproj @@ -11,7 +11,7 @@ true true system;linq;dynamic;core;dotnet;NETCoreApp;NETStandard - Bugfixes and new Features. For details see the release notes. + Bugfixes and new Features. For details see CHANGELOG.md https://github.com/StefH/System.Linq.Dynamic.Core https://github.com/StefH/System.Linq.Dynamic.Core/blob/master/licence.txt git