Skip to content
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

Query Projection int to enum Mapping Issue #226

Open
3 tasks done
marcocavanna opened this issue Sep 21, 2022 · 3 comments
Open
3 tasks done

Query Projection int to enum Mapping Issue #226

marcocavanna opened this issue Sep 21, 2022 · 3 comments
Labels

Comments

@marcocavanna
Copy link

marcocavanna commented Sep 21, 2022

Hi all!

First of all, congratulations on the excellent work of this tool that I'm starting to love and use every day!

The issue I'm facing out is the following (I'm using EFCore with SQLServer):
When using the _myContext.MySet.Where(e => e.Anything == "something").Project().To<MyModel>().ToList() I'm receiving this error:

         - The client projection contains a reference to a constant expression of 'int[]' which is being passed as an argument to the method 'Contains'. This could potentially cause a memory leak; consider assigning this constant to a local variable and using the variable in the query instead. See https://go.microsoft.com/fwlink/?linkid=2103067 for more information.
              at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.ConstantVerifyingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
              at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
              at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
              at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)
              at System.Linq.Expressions.ConditionalExpression.Accept(ExpressionVisitor visitor)
              at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
              at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node)
              at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
              at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor)
              at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node)
              [ ... other useless lines of Stack Trace ... ]

The error above won't show if I use the standard non projection api _myContext.MySet.Where(e => e.Anything == "something").ToList().Select(e => Mapper.Map(e).ToNew<MyModel>()).

After some tests on the code I realized that this problem comes from the projection of a value of type int to an enum, but this happen only when using Project().To<Something>() and not Map(anything).ToNew<Something>().

I'll use a "standard" Issue Template to expose my problem:

Prerequisites

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed

Expected Behavior

I would like to be able to use the EFCore query projection feature even when the model defined on the database has a data type of type int that must be mapped to an enum

Current Behavior

An error will occur while using _myContext.MySet.Where(e => e.Anything == "something").Project().To<MyModel>().ToList() when the Model of _myContext.MySet has a property with int type but the MyModel has declared that property with an enum type.

Failure Information (for bugs)

This problem occur only while mapping int to enum. Removing the enum property declaration (or transform type to int instead of enum) everything is working well.

Clarification

The database entities model I'm using are automatically generated using dotate ef db scaffold tool, then I could not change the type of the entity model described in next section at point 1, named MyEntity.

Steps to Reproduce

  1. Create a database entity model like
// Automatically generated from db scaffold
// could not be changed because will be overwritten 
class MyEntity {
  public int Id { get; set; }
  public string Name { get; set; }
  public int Status { get; set; }
}
  1. Create the DTO model (and the enum) like
enum EntityStatus {
  OnHold = 0,
  WorkInProgress = 1,
  Done = 2
}

class MyEntityDto {
  public int Id { get; set; }
  public string Name { get; set; }
  public EntityStatus Status { get; set; }
}
  1. In some repository try to get entities projected to DTO
public IEnumerable<MyEntityDto> GetEntities(string search)
  => _myContext.MyEntitySet.Where(e => e.Name.Contains(search)).Project().To<MyEntityDto>().ToListAsync();

When arriving at code described at point 3, boom, the Exception will be thrown.
The issue seems to be an error while building the projection query.


Thanks for your patience reading my long issue description, I hope you arrived here and help me resolving this trouble.

@SteveWilkes
Copy link
Member

Hi!

Thanks for the thorough report! Just to check - what version of EF Core are you using?

All the best,

Steve

@marcocavanna
Copy link
Author

Hi! Currently I'm using one of the latest, but not the last, the 6.0.7.

@SteveWilkes
Copy link
Member

Thanks! The error comes from the projection Expression generated by the mapper including an embedded constant array containing the valid underlying numeric enum values - a Contains() call is performed on the array with the value in the DB column to check if it's a valid enum value.

I'll have to rework the generated Expression to do things differently. Thanks for letting me know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants