-
-
Notifications
You must be signed in to change notification settings - Fork 228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET 8 (and possible all non-NETSTANDARD and higher versions) attempt to load EF 6 types #790
Comments
This is probably related to / the same as #783. Can you try the suggestion described there? |
I initially thought so too, but my understanding is that the The Radzen library calls the Which is here: System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs Line 1495 in f8eddd6
Which then calls the System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs Line 1551 in f8eddd6
Which is instantiating the System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs Line 1575 in f8eddd6
Which is instantiating the
Of which the static constructor is loading the
It's the static constructor of the From my understanding, the
|
I had some time to further test this. So, there are 2 things in play:
For that, I believe the same as with the
So, for now I've managed worked around it. |
We see the exact same issue in our application (which happens to also use the Radzen DataGrid that ends up calling the .Order). I'm not sure how to implement a custom type provider as was suggested, but I'd very much appreciate any fix or workaround to improve the performance as the wait is considerable. |
I've used the following implementation, which is a simplified type finder. It doesn't use anything related to the public class CustomDynamicLinqTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
{
public HashSet<Type> GetCustomTypes()
=> GetCustomTypesInternal();
public Dictionary<Type, List<MethodInfo>> GetExtensionMethods()
=> GetExtensionMethodsInternal();
public Type? ResolveType(string typeName)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var type = ResolveType(assemblies, typeName);
return type;
}
public Type? ResolveTypeBySimpleName(string simpleTypeName)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var type = ResolveTypeBySimpleName(assemblies, simpleTypeName);
return type;
}
private HashSet<Type> GetCustomTypesInternal()
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
var hashSet = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
return hashSet;
}
private Dictionary<Type, List<MethodInfo>> GetExtensionMethodsInternal()
{
var types = GetCustomTypes();
var list = new List<Tuple<Type, MethodInfo>>();
foreach (var type in types)
{
var extensionMethods = type
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.IsDefined(typeof(ExtensionAttribute), false))
.ToList();
extensionMethods.ForEach(x => list.Add(new Tuple<Type, MethodInfo>(x.GetParameters()[0].ParameterType, x)));
}
return list.GroupBy(x => x.Item1, tuple => tuple.Item2).ToDictionary(key => key.Key, methods => methods.ToList());
}
} Then, in my ParsingConfig.Default.CustomTypeProvider = new CustomDynamicLinqTypeProvider(); |
@jnsn / @BoudewijnPopkema
|
We are using 2. Microsoft.EntityFrameworkCore.DynamicLinq version 8.3.10 |
I've added some workaround logic to only load the old EF when a special EFType is found. Would this solve your issue in .NET 8 ? |
I'm using the Radzen library, so my use of But as I mentioned earlier, some of these types are excluded using a NETSTANDARD preprocessor directive. Is there a reason these aren't excluded in anything more recent than NETSTANDARD, like NETCOREAPP3_1 and higher? |
@jnsn Can you please provide a simple console app which shows your issue? This makes it easier for me to check if this fix solves that problem. |
Maybe I'm not understanding it entirely. To me, it looks like these types should only exist in a Full Framework environment, as they are from EF 6. In .NET Core or .NET 5 and higher projects, these will never exist. Or at least never loaded from the Full Framework EF 6 libraries, but always from potential EFCore libraries, if at all. The
I've attached a ZIP file which contains 2 projects: linq-core-demo.zip
I've also included a The
As you can see from the output, all the EF types are attempted to be resolved from by The main issue is the attempted load of the |
1️⃣I did change the code for PredefinedTypesHelper so that it checks for static PredefinedTypesHelper()
{
if (Type.GetType("EntityFramework.DynamicLinq.EFType, EntityFramework.DynamicLinq") != null)
{
TryAdd("System.Data.Objects.EntityFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 1);
TryAdd("System.Data.Objects.SqlClient.SqlFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 1);
TryAdd("System.Data.Objects.SqlClient.SqlSpatialFunctions, System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 1);
TryAdd("System.Data.Entity.Core.Objects.EntityFunctions, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 2);
TryAdd("System.Data.Entity.DbFunctions, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 2);
TryAdd("System.Data.Entity.Spatial.DbGeography, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 2);
TryAdd("System.Data.Entity.SqlServer.SqlFunctions, EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 2);
TryAdd("System.Data.Entity.SqlServer.SqlSpatialFunctions, EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 2);
}
if (Type.GetType($"Microsoft.EntityFrameworkCore.DynamicLinq.EFType, Microsoft.EntityFrameworkCore.DynamicLinq, Version={Version}, Culture=neutral, PublicKeyToken={PublicKeyToken}") != null)
{
TryAdd($"Microsoft.EntityFrameworkCore.DynamicLinq.DynamicFunctions, Microsoft.EntityFrameworkCore.DynamicLinq, Version={Version}, Culture=neutral, PublicKeyToken={PublicKeyToken}", 3);
}
} Which results now in:
(Maybe this is not yet perfect, but it's a workaround) 2️⃣Note that the last call is done via the Loading from these extra files could be made configurable via the Config. So by default it will not load extra files which are not referenced by the main program. |
I don't think that will solve the issue for me, as nothing changes in the behavior that I'm trying to avoid. It's still loading in the hundreds of From my testing, I believe the problem is that the I still believe the issue is located here:
As the comment on line 53 suggest, that should only be done in case of the full framework. I believe the fix is to add the |
A]I've added See: System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs Line 64 in da82150
B]Adding C]
I've implemented option 2️⃣ by adding a extra config setting: /// <summary>
/// Load additional assemblies from the current domain base directory.
///
/// Note: only used when full .NET Framework and .NET Core App 2.x and higher.
///
/// Default value is <c>false</c>.
/// </summary>
public bool LoadAdditionalAssembliesFromCurrentDomainBaseDirectory { get; set; } Default it's See logging from that demo-app:
|
@jnsn Did you have time to take a look at my comment? |
Hi, Sorry for the late reply. This indeed looks like it would fix the issue for me. Thanks! |
After upgrading one of our projects from .NET Core 3.1 to .NET 8 we were seeing a performance issue when using a Radzen data grid that is loaded or sorted for the first time when an entire list is directly bound to it. After some debugging I was able to narrow it to the usage of the
OrderBy
method in this library that is being used.The static constructor of the
PredefinedTypesHelper
class attempts to load a set of types fromSyste.Data.Objects
andSystem.Data.Entity
. There is a list of preprocessor directives around it which, I believe, should only be triggered in full .NET framework cases.System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs
Lines 54 to 75 in 5cf8357
Our old implementation had a .NET Standard class library loading the Radzen library, which in turn loaded System.Linq.Dynamic.Core. This resulted in the NETSTANDARD directive being set, so the entire block was discarded. Our new implementation upgraded everything to .NET 8, were the NETSTANDARD flag is not set this the entire set of types is loaded.
Due to the nature of our deployment we have a lot of assemblies in the working directory which might or might not need to be loaded depending on the configuration. So they are not necessarily already present in the AppDomain but exist on disk in the current working directory.
The
Type.GetType(typeName);
call will force load all the assemblies in the current folder to be loaded in the AppDomain. If there are hundreds of assemblies there, this takes quite some time and results in the performance impact we are seeing.The text was updated successfully, but these errors were encountered: