0

I'd like to have an expression that converts an entity item into a DTO object and use an additional parameter to select which data should be copied into the DTO. This works very well until I add the parameter:

    private static readonly Expression<Func<User, UserDataGroupType, UserData>> s_entityToDataExpression = (User entity, UserDataGroupType dataGroups) => new UserData
    {
        Id = entity.Id,
        State = entity.State,

        Role = entity.Role.ToData(),

        BaseData = dataGroups.HasFlag(UserDataGroupType.Base) ? entity.ToDataBase() : null,
        BirthData = dataGroups.HasFlag(UserDataGroupType.Birth) ? entity.ToDataBirth() : null,
        AddressData = dataGroups.HasFlag(UserDataGroupType.Address) ? entity.ToDataAddress() : null,
        ExtendedData = dataGroups.HasFlag(UserDataGroupType.Extended) ? entity.ToDataExtended() : null,
    };

private static readonly Func<User, UserDataGroupType, UserData> s_entityToDataDelegate = s_entityToDataExpression.Compile();

public static UserData ToData(this User entity, UserDataGroupType dataGroups) => s_entityToDataDelegate(entity, dataGroups);

public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) => queryable.Select(s_entityToDataExpression);

It complains at the parameter of the the last line:

cannot convert from 'System.Linq.Expressions.Expression<System.Func<Entities.User, Enums.UserDataGroupType, UserData>>' to 'System.Linq.Expressions.Expression<System.Func<Entities.User, int, UserData>>'

Where is that int coming from? UserDataGroupType is a byte type flag enum.

Update

After the modifications suggested by @guru-stron the working code looks like this:

private static Expression<Func<User, UserData>> GetToDataExpression(UserDataGroupType dataGroups) => (entity) => new UserData {...}
public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) => queryable.Select(GetToDataExpression(dataGroups));

1 Answer 1

1

Queryable.Select has 2 overloads with Func's with one and two parameters -

  • Select<TSource,TResult>(IQueryable<TSource>, Expression<Func<TSource,Int32,TResult>>)
  • Select<TSource,TResult>(IQueryable<TSource>, Expression<Func<TSource,TResult>>)

The first one representing the expression like .Select((item, index) => ...), your s_entityToDataExpression represents a Func requiring 2 parameters so compiler tries to cast it to Expression<System.Func<Entities.User, int, UserData>>, which is not possible.

It looks like you need to change your code to something like:

private static Expression<Func<User, UserData>> GetExpression(UserDataGroupType dataGroups) => (User entity, UserDataGroupType ) => new UserData
{
    Id = entity.Id,
    State = entity.State,

    Role = entity.Role.ToData(),

    BaseData = dataGroups.HasFlag(UserDataGroupType.Base) ? entity.ToDataBase() : null,
    BirthData = dataGroups.HasFlag(UserDataGroupType.Birth) ? entity.ToDataBirth() : null,
    AddressData = dataGroups.HasFlag(UserDataGroupType.Address) ? entity.ToDataAddress() : null,
    ExtendedData = dataGroups.HasFlag(UserDataGroupType.Extended) ? entity.ToDataExtended() : null,
};

public static IQueryable<UserData> ToData(this IQueryable<User> queryable, UserDataGroupType dataGroups) 
     => queryable.Select(GetExpression(dataGroups));
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.