Skip to content

Argument Exception : Property is not defined when mapping a lambda using properties of child object #41

@Poilaupat

Description

@Poilaupat

Hello,
I'm stuck with a specific scenario in ExpressionMapper.
In the reproduction code below (a simple console app), in the last mapping I have an ArgumentException saying "Property 'System.DateTime EventDate' is not defined for Type TestExpressionMapper.EventEntity" which is obviously wrong since the property exists on the class. Is there any mistake in my code or in the way i'm using ExpressionMapper or is it a non-covered scenario ? If so, is there a known workaround ?

Thanks !

public class TestExpressionMapper
    {
        private static IMapper _mapper;

        static void Main()
        {
            #region Populate test

            List<EmployeeEntity> empEntity = new List<EmployeeEntity>
            {
                new EmployeeEntity { Id = 1, Name = "Jean-Louis", Age = 39, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
                new EmployeeEntity { Id = 2, Name = "Jean-Paul", Age = 32, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
                new EmployeeEntity { Id = 3, Name = "Jean-Christophe", Age = 19, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
                new EmployeeEntity { Id = 4, Name = "Jean-Marie", Age = 27, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-3) } }.ToList() },
                new EmployeeEntity { Id = 5, Name = "Jean-Marc", Age = 22, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-5) } }.ToList() },
                new EmployeeEntity { Id = 5, Name = "Jean-Pierre", Age = 22, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-5) } }.ToList() },
                new EmployeeEntity { Id = 6, Name = "Christophe", Age = 55, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
                new EmployeeEntity { Id = 7, Name = "Marc", Age = 23, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
                new EmployeeEntity { Id = 8, Name = "Paul", Age = 38, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-10) }, new EventEntity { EventType = "Stop", EventDate = DateTime.Today.AddYears(-1) } }.ToList() },
                new EmployeeEntity { Id = 9, Name = "Jean", Age = 32, Events = new EventEntity[]{ new EventEntity { EventType = "Start", EventDate = DateTime.Today.AddYears(-10) }, new EventEntity { EventType = "Stop", EventDate = DateTime.Today.AddYears(-2) } }.ToList() },
            };

            #endregion

            #region Mapping config

            _mapper = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<EmployeeModel, EmployeeEntity>().ReverseMap();
                cfg.CreateMap<EventModel, EventEntity>().ReverseMap();
            }).CreateMapper();

            _mapper.ConfigurationProvider.AssertConfigurationIsValid();

            #endregion

            #region Test

            Expression<Func<EmployeeModel, bool>> filter;
            Expression<Func<EmployeeEntity, bool>> mappedFilter;

            // Works : Returns employees whose name starts with "Jean"
            filter = emp => emp.Name.StartsWith("Jean");
            mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
            var res1 = empEntity.AsQueryable().Where(mappedFilter);

            //Works : Returns employees having at least one "Stop" event
            filter = emp => emp.Events.Any(evt => evt.EventType.Equals("Stop"));
            mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
            var res2 = empEntity.AsQueryable().Where(mappedFilter);

            //Works : Returns employees having any event older than 3 years
            filter = emp => emp.Events.Any(evt => evt.EventDate < DateTime.Today.AddYears(-3));
            mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
            var res3 = empEntity.AsQueryable().Where(mappedFilter);

            //Works : Returns employees having a stop event older than 1 year (no expression mapping -> lambda is built against entities)
            mappedFilter = emp =>
                emp.Events.Any(e => e.EventType.Equals("Stop")) &&
                emp.Events.First(e => e.EventType.Equals("Stop")).EventDate < DateTime.Today.AddYears(-1);
            var res4 = empEntity.AsQueryable().Where(mappedFilter);

            //Breaks on mapping : Same lambda as previous one but built against models then mapped
            filter = emp =>
                emp.Events.Any(e => e.EventType.Equals("Stop")) &&
                emp.Events.First(e => e.EventType.Equals("Stop")).EventDate < DateTime.Today.AddYears(-1);
            mappedFilter = _mapper.MapExpression<Expression<Func<EmployeeEntity, bool>>>(filter);
            var res5 = empEntity.AsQueryable().Where(mappedFilter);

            #endregion

            Console.ReadKey();
        }

    }

    internal class EmployeeEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public List<EventEntity> Events { get; set; }
    }

    internal class EventEntity
    {
        public string EventType { get; set; }
        public DateTime EventDate { get; set; }
    }


    internal class EmployeeModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public List<EventModel> Events { get; set; }
    }

    internal class EventModel
    {
        public string EventType { get; set; }
        public DateTime EventDate { get; set; }
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions