AutoMapper ProjectTo is throwing an error on anything newer than version 5.8.7

Posts   
 
    
jsam
User
Posts: 4
Joined: 07-Dec-2022
# Posted on: 07-Dec-2022 20:18:37   

AutoMapper ProjectTo is throwing an error on anything newer than version 5.8.7. AutoMapper version does not matter, I have tried version 8 to12. Project is on .NET 6. I tried building LLBLGen project in .NET 6 and .NET Standard 2.1

Code:

using (var adapter = new DataAccessAdapter())
{
    var metaData = new LinqMetaData(adapter);

    var clientQuery =
    (
        from q in metaData.Customer
        where q.CustomerId == 45
        select q
    );

    var onecustomer = await clientQuery
        .ProjectTo<Customer>(_mapper.ConfigurationProvider)
        .FirstOrDefaultAsync(cancellationToken);
}
InnerException = {"Method not found: 'Void SD.LLBLGen.Pro.ORMSupportClasses.EntityFactoryCore2..ctor(System.String)'."}
at IsDataCore.FactoryClasses.ElementCreator.GetFactoryImpl(Type typeOfEntity) 
at IsDataCore.FactoryClasses.ElementCreator.GetFactory(Type typeOfEntity) 
at SD.LLBLGen.Pro.LinqSupportClasses.LinqUtils.GetFactoryInstanceForEntityType(Type entityType, IElementCreatorCore generatedCodeElementCreator) 
at SD.LLBLGen.Pro.LinqSupportClasses.LinqUtils.HandleMemberMappedOnRelationIsPartOfEntity(MemberExpression expressionToHandle, Expression memberContainer, MappingTracker trackedMappings, IElementCreatorCore generatedCodeElementCreator) 
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMemberExpression(MemberExpression expressionToHandle) 
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) 
at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpressionList(ReadOnlyCollection1 listToHandle)
 at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleDefaultOperatorOverloadMethod(MethodCallExpression expressionToHandle, StandardOperatorType operatorType)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleBinaryExpression(BinaryExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleLambdaExpression(LambdaExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallWhere(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleQueryableExtensionMethod(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallPerType(MethodCallExpression expressionToHandle, Type declaringType)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallSelect(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleQueryableExtensionMethod(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallPerType(MethodCallExpression expressionToHandle, Type declaringType)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallFirstSingle(MethodCallExpression expressionToHandle, Boolean isSingle, Boolean isDefault)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleQueryableExtensionMethod(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallPerType(MethodCallExpression expressionToHandle, Type declaringType)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.PreProcessor.HandleMethodCallExpression(MethodCallExpression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle)
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.HandleExpressionTree(Expression expression)
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.<PerformExecuteAsync>d__30.MoveNext()
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.<ExecuteAsync>d__291.MoveNext() at SD.LLBLGen.Pro.LinqSupportClasses.QueryableExtensionMethods.<FirstOrDefaultAsync>d__1091.MoveNext()
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39730
Joined: 17-Aug-2003
# Posted on: 08-Dec-2022 09:46:10   

Is your generated code also of the same version as the runtime you're using? As the code assumes a type in the generated code to be there but it's not found. E.g. the generated code of IsDataCore.FactoryClasses.ElementCreator.GetFactoryImpl(Type typeOfEntity)

It also looks like you copy/pasted the stacktrace from multiple sources?

Frans Bouma | Lead developer LLBLGen Pro
jsam
User
Posts: 4
Joined: 07-Dec-2022
# Posted on: 08-Dec-2022 09:59:35   

I am using v5.9 RTM to generate the code targeting NET 6. If I use runtime 5.9.x it gives this error. If I use runtime version 5.8.7 or below it works without issue.

Yes, I copied the inner exception and stack trace. Removed some of the references to our internal code to keep it anonymous.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39730
Joined: 17-Aug-2003
# Posted on: 08-Dec-2022 10:38:40   

The end of the stack trace that is important:

InnerException = {"Method not found: 'Void SD.LLBLGen.Pro.ORMSupportClasses.EntityFactoryCore2..ctor(System.String)'."}
at IsDataCore.FactoryClasses.ElementCreator.GetFactoryImpl(Type typeOfEntity) 
at IsDataCore.FactoryClasses.ElementCreator.GetFactory(Type typeOfEntity) 

I think there's something wrong with your generated code. Please open the FactoryClasses\EntityFactories.cs file in your generated code, then go to the bottom where you'll find ElementCreator. this is a generic object that's passed around to the linq provider so it can create instances when needed. I'll show below how it looks in Northwind generated adapter code:

/// <summary>Element creator for creating project elements from somewhere else, like inside Linq providers.</summary>
public class ElementCreator : ElementCreatorBase, IElementCreator2
{
    /// <summary>Gets the factory of the Entity type with the Northwind.Adapter.EntityType value passed in</summary>
    /// <param name="entityTypeValue">The entity type value.</param>
    /// <returns>the entity factory of the entity type or null if not found</returns>
    public IEntityFactory2 GetFactory(int entityTypeValue) { return (IEntityFactory2)this.GetFactoryImpl(entityTypeValue); }

which then calls into:

protected override IEntityFactoryCore GetFactoryImpl(int entityTypeValue) { return EntityFactoryFactory.GetFactory((Northwind.Adapter.EntityType)entityTypeValue); }

which then calls into:

/// <summary>Gets the factory of the entity with the Northwind.Adapter.EntityType specified</summary>
/// <param name="typeOfEntity">The type of entity.</param>
/// <returns>factory to use or null if not found</returns>
public static IEntityFactory2 GetFactory(Northwind.Adapter.EntityType typeOfEntity)
{
    switch(typeOfEntity)
    {
        case Northwind.Adapter.EntityType.CategoryEntity:
            return new CategoryEntityFactory();
        case Northwind.Adapter.EntityType.CompoundWithSelfEntity:
            return new CompoundWithSelfEntityFactory();
        case Northwind.Adapter.EntityType.CustomerEntity:
            return new CustomerEntityFactory();
        case Northwind.Adapter.EntityType.CustomerCustomerDemoEntity:
            return new CustomerCustomerDemoEntityFactory();
        case Northwind.Adapter.EntityType.CustomerDemographicsEntity:
            return new CustomerDemographicsEntityFactory();
        case Northwind.Adapter.EntityType.EmployeeEntity:
            return new EmployeeEntityFactory();
        case Northwind.Adapter.EntityType.EmployeeTerritoriesEntity:
            return new EmployeeTerritoriesEntityFactory();
        case Northwind.Adapter.EntityType.OrderEntity:
            return new OrderEntityFactory();
        case Northwind.Adapter.EntityType.OrderDetailsEntity:
            return new OrderDetailsEntityFactory();
        case Northwind.Adapter.EntityType.ProductEntity:
            return new ProductEntityFactory();
        case Northwind.Adapter.EntityType.ProductWEnumEntity:
            return new ProductWEnumEntityFactory();
        case Northwind.Adapter.EntityType.RegionEntity:
            return new RegionEntityFactory();
        case Northwind.Adapter.EntityType.ShipperEntity:
            return new ShipperEntityFactory();
        case Northwind.Adapter.EntityType.SupplierEntity:
            return new SupplierEntityFactory();
        case Northwind.Adapter.EntityType.TCTesterEntity:
            return new TCTesterEntityFactory();
        case Northwind.Adapter.EntityType.TerritoryEntity:
            return new TerritoryEntityFactory();
        default:
            return null;
    }
}

so this calls the regular ctor of the entity factory of the type. Say you wanted Customer here, then it calls into the CustomerEntityFactory() ctor:

/// <summary>Factory to create new, empty CustomerEntity objects.</summary>
[Serializable]
public partial class CustomerEntityFactory : EntityFactoryBase2<CustomerEntity> 
{
    /// <summary>CTor</summary>
    public CustomerEntityFactory() : base("CustomerEntity", Northwind.Adapter.EntityType.CustomerEntity, false) { }
    /// <inheritdoc/>
    protected override IEntity2 CreateImpl(IEntityFields2 fields) { return new CustomerEntity(fields); }
}

As these factories all inherit from a generated base class, it calls into:

public partial class EntityFactoryBase2<TEntity> : EntityFactoryCore2
    where TEntity : EntityBase2, IEntity2
{
    private readonly bool _isInHierarchy;

    /// <summary>CTor</summary>
    /// <param name="entityName">Name of the entity.</param>
    /// <param name="typeOfEntity">The type of entity.</param>
    /// <param name="isInHierarchy">If true, the entity of this factory is in an inheritance hierarchy, false otherwise</param>
    public EntityFactoryBase2(string entityName, Northwind.Adapter.EntityType typeOfEntity, bool isInHierarchy) : base(entityName, (int)typeOfEntity)
    {
        _isInHierarchy = isInHierarchy;
    }

And finally, after all these shenanigans we're at the core of the problem simple_smile Here you see that the ctor calls the base ctor in the runtime with 2 parameters. I think your generated code here calls a base method with 1 argument (so not the (int)typeOfEntity). The change here was introduced in 5.9.0 to optimize some internals (Dependency injection shouldn't take place for dummy entity instances which are created for query generation).

My suspicion is that your generated code here used at runtime isn't generated with v5.9. Could you check your files if it looks like what I described above?

Frans Bouma | Lead developer LLBLGen Pro
jsam
User
Posts: 4
Joined: 07-Dec-2022
# Posted on: 08-Dec-2022 13:42:27   

You are correct. I was referencing an older version generated using 5.6. Thank you for the help !