0

I've inherited a c# winforms application developed as single user. It uses EF 6 DB First, AutoMapper 4.2.1, Generic Repository and Uow . When using local database the application behaves well enough but when using remote database (vpn connection to server) the application is very slow especially due to some calls which uses AutoMapper. This issue is also described in the following question : [https://stackoverflow.com/questions/66706496/entity-framework-6-generic-repository-with-automapper-slow-performance-when-runn][1]

As [2]: https://stackoverflow.com/users/1663001/davidg suggested the reason for why the application is running slow is because I'm downloading the entire list of users from the database and filtering in memory.

public List<T1> Find(Expression<Func<T1, bool>> predicate)
{
    // Note this is still an IQueryable<T> so nothing is executed against the database yet
    var query = _dbContext.Set<T>()
        .Where(q => !q.IsDeleted)
        .Where(predicate);

    return AutoMapperConfiguration.GetMapperConfiguration()
        .Map<List<T1>>(query);
}

The main issue here is that I cannot apply predicate in the query where clause because it is expected a predicate of type Expression<Func<T1, bool>> where T1 is my PrjUser_ViewModel class and T1 is PrjUser Entity class.

So I'm looking for a way to convert Expression<Func<T1, bool>> predicate into Expression<Func<T, bool>> predicate in order to improve the performance and reduce the time spent in each call of the Find method. Any answers will be highly appreciated.

UPDATE, This is the Automapper mapper configuration class

public static class AutoMapperConfiguration
    {
        private static IMapper mapperConfiguration;
        
        public static IMapper GetMapperConfiguration()
        {
            return mapperConfiguration;
        }

        public static void SetMapperConfiguration(IMapper value)
        {
            mapperConfiguration = value;
        }

        public static void Configure()
        {
            var config = new MapperConfiguration(cfg =>
            cfg.AddProfile(new MapperProfile()));

            SetMapperConfiguration(config.CreateMapper());
        }
    }
}

Edit I'm adding the entire configuration of Automapper inside my project :

AutoMapperConfiguration.cs

using AutoMapper;



    public static class AutoMapperConfiguration
    {
        private static IMapper mapperConfiguration;
        
        public static IMapper GetMapperConfiguration()
        {
            return mapperConfiguration;
        }

        public static void SetMapperConfiguration(IMapper value)
        {
            mapperConfiguration = value;
        }

        public static void Configure()
        {
            var config = new MapperConfiguration(cfg =>
            cfg.AddProfile(new MapperProfile()));

            SetMapperConfiguration(config.CreateMapper());
        }
    }

IgnoreVirtualExtensions.cs

public static IMappingExpression<TSource, TDestination>
               IgnoreAllVirtual<TSource, TDestination>(
                   this IMappingExpression<TSource, TDestination> expression)
        {
            var desType = typeof(TDestination);
            foreach (var property in desType.GetProperties().Where(p =>
                                     p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal))
            {
                expression.ForMember(property.Name, opt => opt.Ignore());
            }

            return expression;
        }
    }

MapperProfile.cs

internal class MapperProfile : AutoMapper.Profile
    {
        protected override void Configure()
        {

.......................
            CreateMap<PrjUser, PrjUser_ViewModel>().ForMember(dest => dest.ConfigSets_LockedBy, opt => opt.MapFrom(src => src.ConfigSets1))
                                                    .ForMember(dest => dest.ConfigSet_Attribute_LockedBy, opt => opt.MapFrom(src => src.ConfigSet_Attribute1))
                                                    .ForMember(dest => dest.ConfigSet_DataType_Mapping_LockedBy, opt => opt.MapFrom(src => src.ConfigSet_DataType_Mapping1))
                                                    .ForMember(dest => dest.ConfigSet_IODPEntity_Mapping_LockedBy, opt => opt.MapFrom(src => src.ConfigSet_IODPEntity_Mapping1))
                                                    .ForMember(dest => dest.DataTypes_LockedBy, opt => opt.MapFrom(src => src.DataTypes1))
                                                    .ForMember(dest => dest.Features_LockedBy, opt => opt.MapFrom(src => src.Features1))
                                                    .ForMember(dest => dest.GeneralParameters_LockedBy, opt => opt.MapFrom(src => src.GeneralParameters1))
                                                    .ForMember(dest => dest.HwVariants_LockedBy, opt => opt.MapFrom(src => src.HwVariants1))
                                                    .ForMember(dest => dest.HwVariantConfigurationMappings_LockedBy, opt => opt.MapFrom(src => src.HwVariantConfigurationMappings1))
                                                    .ForMember(dest => dest.IODPEntities_LockedBy, opt => opt.MapFrom(src => src.IODPEntities1))
                                                    .ForMember(dest => dest.MainFunctions_LockedBy, opt => opt.MapFrom(src => src.MainFunctions1))
                                                    .ForMember(dest => dest.MainFunction_Attribute_LockedBy, opt => opt.MapFrom(src => src.MainFunction_Attribute1))
                                                    .ForMember(dest => dest.Modules_LockedBy, opt => opt.MapFrom(src => src.Modules1))
                                                    .ForMember(dest => dest.Module_Feature_Mapping_LockedBy, opt => opt.MapFrom(src => src.Module_Feature_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntities_LockedBy, opt => opt.MapFrom(src => src.ModuleEntities1))
                                                    .ForMember(dest => dest.ModuleEntity_Association_LockedBy, opt => opt.MapFrom(src => src.ModuleEntity_Association1))
                                                    .ForMember(dest => dest.ModuleEntity_Attribute_LockedBy, opt => opt.MapFrom(src => src.ModuleEntity_Attribute1))
                                                    .ForMember(dest => dest.ModuleEntity_DataType_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntity_DataType_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntity_HwVariant_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntity_HwVariant_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntity_IODPEntity_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntity_IODPEntity_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_Attribute_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_Attribute1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_ConfigSet_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_ConfigSet_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_MainFunction_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_MainFunction_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_Signal_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_Signal_Mapping1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariantSignal_Attribute_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariantSignal_Attribute1))
                                                    .ForMember(dest => dest.ModuleEntityHwVariantSignal_Plausibility_Mapping_LockedBy, opt => opt.MapFrom(src => src.ModuleEntityHwVariantSignal_Plausibility_Mapping1))
                                                    .ForMember(dest => dest.ModuleProperty_Attribute_LockedBy, opt => opt.MapFrom(src => src.ModuleProperty_Attribute1))
                                                    .ForMember(dest => dest.Plausibilities_LockedBy, opt => opt.MapFrom(src => src.Plausibilities1))
                                                    .ForMember(dest => dest.Plausibility_Attribute_LockedBy, opt => opt.MapFrom(src => src.Plausibility_Attribute1))
                                                    .ForMember(dest => dest.Preferences_LockedBy, opt => opt.MapFrom(src => src.Preferences1))
                                                    .ForMember(dest => dest.Signal_Attribute_LockedBy, opt => opt.MapFrom(src => src.Signal_Attribute1))
                                                    .ForMember(dest => dest.Signal_DataType_Mapping_LockedBy, opt => opt.MapFrom(src => src.Signal_DataType_Mapping1))
                                                    .ForMember(dest => dest.Signal_IODPEntity_Mapping_LockedBy, opt => opt.MapFrom(src => src.Signal_IODPEntity_Mapping1))
                                                    .ForMember(dest => dest.Signal_ModuleEntity_Mapping_LockedBy, opt => opt.MapFrom(src => src.Signal_ModuleEntity_Mapping1))
                                                    .ForMember(dest => dest.Signals_LockedBy, opt => opt.MapFrom(src => src.Signals1))
                                                    .ForMember(dest => dest.Types_LockedBy, opt => opt.MapFrom(src => src.Types1))
                                                    .ForMember(dest => dest.ValidValues_LockedBy, opt => opt.MapFrom(src => src.ValidValues1));
            CreateMap<PrjUser, PrjUser_ViewModel>().ReverseMap().ForMember(dest => dest.ConfigSet_Attribute1, opt => opt.MapFrom(src => src.ConfigSets_LockedBy))
                                                    .ForMember(dest => dest.ConfigSet_DataType_Mapping1, opt => opt.MapFrom(src => src.ConfigSet_Attribute_LockedBy))
                                                    .ForMember(dest => dest.ConfigSet_IODPEntity_Mapping1, opt => opt.MapFrom(src => src.ConfigSet_DataType_Mapping_LockedBy))
                                                    .ForMember(dest => dest.DataTypes1, opt => opt.MapFrom(src => src.ConfigSet_IODPEntity_Mapping_LockedBy))
                                                    .ForMember(dest => dest.Features1, opt => opt.MapFrom(src => src.DataTypes_LockedBy))
                                                    .ForMember(dest => dest.GeneralParameters1, opt => opt.MapFrom(src => src.Features_LockedBy))
                                                    .ForMember(dest => dest.HwVariants1, opt => opt.MapFrom(src => src.GeneralParameters_LockedBy))
                                                    .ForMember(dest => dest.HwVariantConfigurationMappings1, opt => opt.MapFrom(src => src.HwVariantConfigurationMappings_LockedBy))
                                                    .ForMember(dest => dest.IODPEntities1, opt => opt.MapFrom(src => src.IODPEntities_LockedBy))
                                                    .ForMember(dest => dest.MainFunctions1, opt => opt.MapFrom(src => src.MainFunctions_LockedBy))
                                                    .ForMember(dest => dest.MainFunction_Attribute1, opt => opt.MapFrom(src => src.MainFunction_Attribute_LockedBy))
                                                    .ForMember(dest => dest.Modules1, opt => opt.MapFrom(src => src.Modules_LockedBy))
                                                    .ForMember(dest => dest.Module_Feature_Mapping1, opt => opt.MapFrom(src => src.Module_Feature_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntities1, opt => opt.MapFrom(src => src.ModuleEntities_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntity_Association1, opt => opt.MapFrom(src => src.ModuleEntity_Association_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntity_Attribute1, opt => opt.MapFrom(src => src.ModuleEntity_Attribute_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntity_DataType_Mapping1, opt => opt.MapFrom(src => src.ModuleEntity_DataType_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntity_HwVariant_Mapping1, opt => opt.MapFrom(src => src.ModuleEntity_HwVariant_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntity_IODPEntity_Mapping1, opt => opt.MapFrom(src => src.ModuleEntity_IODPEntity_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_Attribute1, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_Attribute_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_ConfigSet_Mapping1, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_ConfigSet_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_MainFunction_Mapping1, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_MainFunction_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariant_Signal_Mapping1, opt => opt.MapFrom(src => src.ModuleEntityHwVariant_Signal_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariantSignal_Attribute1, opt => opt.MapFrom(src => src.ModuleEntityHwVariantSignal_Attribute_LockedBy))
                                                    .ForMember(dest => dest.ModuleEntityHwVariantSignal_Plausibility_Mapping1, opt => opt.MapFrom(src => src.ModuleEntityHwVariantSignal_Plausibility_Mapping_LockedBy))
                                                    .ForMember(dest => dest.ModuleProperty_Attribute1, opt => opt.MapFrom(src => src.ModuleProperty_Attribute_LockedBy))
                                                    .ForMember(dest => dest.Plausibilities1, opt => opt.MapFrom(src => src.Plausibilities_LockedBy))
                                                    .ForMember(dest => dest.Plausibility_Attribute1, opt => opt.MapFrom(src => src.Plausibility_Attribute_LockedBy))
                                                    .ForMember(dest => dest.Preferences1, opt => opt.MapFrom(src => src.Preferences_LockedBy))
                                                    .ForMember(dest => dest.Signal_Attribute1, opt => opt.MapFrom(src => src.Signal_Attribute_LockedBy))
                                                    .ForMember(dest => dest.Signal_DataType_Mapping1, opt => opt.MapFrom(src => src.Signal_DataType_Mapping_LockedBy))
                                                    .ForMember(dest => dest.Signal_IODPEntity_Mapping1, opt => opt.MapFrom(src => src.Signal_IODPEntity_Mapping_LockedBy))
                                                    .ForMember(dest => dest.Signal_ModuleEntity_Mapping1, opt => opt.MapFrom(src => src.Signal_ModuleEntity_Mapping_LockedBy))
                                                    .ForMember(dest => dest.Signals1, opt => opt.MapFrom(src => src.Signals_LockedBy))
                                                    .ForMember(dest => dest.Types1, opt => opt.MapFrom(src => src.Types_LockedBy))
                                                    .ForMember(dest => dest.ValidValues1, opt => opt.MapFrom(src => src.ValidValues_LockedBy));      

..................................   
        }
    }

and PrjUsers_ViewModel

public class PrjUser_ViewModel : IEntity
{
    public PrjUser_ViewModel()
    {
        this.ConfigSets = new HashSet<ConfigSet_ViewModel>();
        this.ConfigSet_Attribute = new HashSet<ConfigSet_Attribute_ViewModel>();
        this.ConfigSet_DataType_Mapping = new HashSet<ConfigSet_DataType_Mapping_ViewModel>();
        this.ConfigSet_IODPEntity_Mapping = new HashSet<ConfigSet_IODPEntity_Mapping_ViewModel>();
        this.DataTypes = new HashSet<DataType_ViewModel>();
        this.Features = new HashSet<Feature_ViewModel>();
        this.GeneralParameters = new HashSet<GeneralParameter_ViewModel>();
        this.HwVariants = new HashSet<HwVariant_ViewModel>();
        this.HwVariants_LockedBy = new HashSet<HwVariant_ViewModel>();
        this.IODPEntities = new HashSet<IODPEntity_ViewModel>();
        this.MainFunctions = new HashSet<MainFunction_ViewModel>();
        this.MainFunction_Attribute = new HashSet<MainFunction_Attribute_ViewModel>();
        this.Modules = new HashSet<Module_ViewModel>();
        this.Module_Feature_Mapping = new HashSet<Module_Feature_Mapping_ViewModel>();
        this.ModuleEntities = new HashSet<ModuleEntity_ViewModel>();
        this.ModuleEntity_Association = new HashSet<ModuleEntity_Association_ViewModel>();
        this.ModuleEntity_Attribute = new HashSet<ModuleEntity_Attribute_ViewModel>();
        this.ModuleEntity_HwVariant_Mapping = new HashSet<ModuleEntity_HwVariant_Mapping_ViewModel>();
        this.ModuleEntity_DataType_Mapping = new HashSet<ModuleEntity_DataType_Mapping_ViewModel>();
        this.ModuleEntity_IODPEntity_Mapping = new HashSet<ModuleEntity_IODPEntity_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_Attribute = new HashSet<ModuleEntityHwVariant_Attribute_ViewModel>();
        this.ModuleEntityHwVariant_ConfigSet_Mapping = new HashSet<ModuleEntityHwVariant_ConfigSet_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_MainFunction_Mapping = new HashSet<ModuleEntityHwVariant_MainFunction_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_Signal_Mapping = new HashSet<ModuleEntityHwVariant_Signal_Mapping_ViewModel>();
        this.ModuleEntityHwVariantSignal_Attribute = new HashSet<ModuleEntityHwVariantSignal_Attribute_ViewModel>();
        this.ModuleEntityHwVariantSignal_Plausibility_Mapping = new HashSet<ModuleEntityHwVariantSignal_Plausibility_Mapping_ViewModel>();
        this.ModuleProperty_Attribute = new HashSet<ModuleProperty_Attribute_ViewModel>();
        this.Plausibilities = new HashSet<Plausibility_ViewModel>();
        this.Plausibility_Attribute = new HashSet<Plausibility_Attribute_ViewModel>();
        this.Preferences = new HashSet<Preferences_ViewModel>();
        this.Signal_Attribute = new HashSet<Signal_Attribute_ViewModel>();
        this.Signal_DataType_Mapping = new HashSet<Signal_DataType_Mapping_ViewModel>();
        this.Signal_IODPEntity_Mapping = new HashSet<Signal_IODPEntity_Mapping_ViewModel>();
        this.Signal_ModuleEntity_Mapping = new HashSet<Signal_ModuleEntity_Mapping_ViewModel>();
        this.Signals = new HashSet<Signal_ViewModel>();
        this.Types = new HashSet<Type_ViewModel>();
        this.ValidValues = new HashSet<ValidValue_ViewModel>();
        this.ConfigSets_LockedBy = new HashSet<ConfigSet_ViewModel>();
        this.ConfigSet_Attribute_LockedBy = new HashSet<ConfigSet_Attribute_ViewModel>();
        this.ConfigSet_DataType_Mapping_LockedBy = new HashSet<ConfigSet_DataType_Mapping_ViewModel>();
        this.ConfigSet_IODPEntity_Mapping_LockedBy = new HashSet<ConfigSet_IODPEntity_Mapping_ViewModel>();
        this.DataTypes_LockedBy = new HashSet<DataType_ViewModel>();
        this.Features_LockedBy = new HashSet<Feature_ViewModel>();
        this.GeneralParameters_LockedBy = new HashSet<GeneralParameter_ViewModel>();
        this.HwVariantConfigurationMappings_LockedBy = new HashSet<HwVariantConfigurationMapping_ViewModel>();
        this.IODPEntities_LockedBy = new HashSet<IODPEntity_ViewModel>();
        this.MainFunctions_LockedBy = new HashSet<MainFunction_ViewModel>();
        this.MainFunction_Attribute_LockedBy = new HashSet<MainFunction_Attribute_ViewModel>();
        this.Modules_LockedBy = new HashSet<Module_ViewModel>();
        this.Module_Feature_Mapping_LockedBy = new HashSet<Module_Feature_Mapping_ViewModel>();
        this.ModuleEntities_LockedBy = new HashSet<ModuleEntity_ViewModel>();
        this.ModuleEntity_Association_LockedBy = new HashSet<ModuleEntity_Association_ViewModel>();
        this.ModuleEntity_Attribute_LockedBy = new HashSet<ModuleEntity_Attribute_ViewModel>();
        this.ModuleEntity_DataType_Mapping_LockedBy = new HashSet<ModuleEntity_DataType_Mapping_ViewModel>();
        this.ModuleEntity_HwVariant_Mapping_LockedBy = new HashSet<ModuleEntity_HwVariant_Mapping_ViewModel>();
        this.ModuleEntity_IODPEntity_Mapping_LockedBy = new HashSet<ModuleEntity_IODPEntity_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_Attribute_LockedBy = new HashSet<ModuleEntityHwVariant_Attribute_ViewModel>();
        this.ModuleEntityHwVariant_ConfigSet_Mapping_LockedBy = new HashSet<ModuleEntityHwVariant_ConfigSet_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_MainFunction_Mapping_LockedBy = new HashSet<ModuleEntityHwVariant_MainFunction_Mapping_ViewModel>();
        this.ModuleEntityHwVariant_Signal_Mapping_LockedBy = new HashSet<ModuleEntityHwVariant_Signal_Mapping_ViewModel>();
        this.ModuleEntityHwVariantSignal_Attribute_LockedBy = new HashSet<ModuleEntityHwVariantSignal_Attribute_ViewModel>();
        this.ModuleEntityHwVariantSignal_Plausibility_Mapping_LockedBy = new HashSet<ModuleEntityHwVariantSignal_Plausibility_Mapping_ViewModel>();
        this.ModuleProperty_Attribute_LockedBy = new HashSet<ModuleProperty_Attribute_ViewModel>();
        this.Plausibilities_LockedBy = new HashSet<Plausibility_ViewModel>();
        this.Plausibility_Attribute_LockedBy = new HashSet<Plausibility_Attribute_ViewModel>();
        this.Preferences_LockedBy = new HashSet<Preferences_ViewModel>();
        this.Signal_Attribute_LockedBy = new HashSet<Signal_Attribute_ViewModel>();
        this.Signal_DataType_Mapping_LockedBy = new HashSet<Signal_DataType_Mapping_ViewModel>();
        this.Signal_IODPEntity_Mapping_LockedBy = new HashSet<Signal_IODPEntity_Mapping_ViewModel>();
        this.Signal_ModuleEntity_Mapping_LockedBy = new HashSet<Signal_ModuleEntity_Mapping_ViewModel>();
        this.Signals_LockedBy = new HashSet<Signal_ViewModel>();
        this.Types_LockedBy = new HashSet<Type_ViewModel>();
        this.ValidValues_LockedBy = new HashSet<ValidValue_ViewModel>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string FullName { get; set; }
    public bool IsDeleted { get; set; }
    public DateTime ModificationDate { get; set; }

    public virtual ICollection<ConfigSet_ViewModel> ConfigSets { get; set; }
    public virtual ICollection<ConfigSet_Attribute_ViewModel> ConfigSet_Attribute { get; set; }
    public virtual ICollection<ConfigSet_DataType_Mapping_ViewModel> ConfigSet_DataType_Mapping { get; set; }
    public virtual ICollection<ConfigSet_IODPEntity_Mapping_ViewModel> ConfigSet_IODPEntity_Mapping { get; set; }
    public virtual ICollection<DataType_ViewModel> DataTypes { get; set; }
    public virtual ICollection<Feature_ViewModel> Features { get; set; }
    public virtual ICollection<HwVariant_ViewModel> HwVariants { get; set; }
    public virtual ICollection<MainFunction_ViewModel> MainFunctions { get; set; }
    public virtual ICollection<MainFunction_Attribute_ViewModel> MainFunction_Attribute { get; set; }
    public virtual ICollection<Module_ViewModel> Modules { get; set; }
    public virtual ICollection<Module_Feature_Mapping_ViewModel> Module_Feature_Mapping { get; set; }
    public virtual ICollection<ModuleEntity_ViewModel> ModuleEntities { get; set; }
    public virtual ICollection<ModuleEntity_Association_ViewModel> ModuleEntity_Association { get; set; }
    public virtual ICollection<ModuleEntity_Attribute_ViewModel> ModuleEntity_Attribute { get; set; }
    public virtual ICollection<ModuleEntity_DataType_Mapping_ViewModel> ModuleEntity_DataType_Mapping { get; set; }
    public virtual ICollection<ModuleEntity_HwVariant_Mapping_ViewModel> ModuleEntity_HwVariant_Mapping { get; set; }
    public virtual ICollection<ModuleEntityHwVariant_Attribute_ViewModel> ModuleEntityHwVariant_Attribute { get; set; }
    public virtual ICollection<ModuleEntityHwVariant_ConfigSet_Mapping_ViewModel> ModuleEntityHwVariant_ConfigSet_Mapping { get; set; }
    public virtual ICollection<ModuleEntityHwVariant_MainFunction_Mapping_ViewModel> ModuleEntityHwVariant_MainFunction_Mapping { get; set; }
    public virtual ICollection<ModuleEntityHwVariant_Signal_Mapping_ViewModel> ModuleEntityHwVariant_Signal_Mapping { get; set; }
    public virtual ICollection<ModuleEntityHwVariantSignal_Attribute_ViewModel> ModuleEntityHwVariantSignal_Attribute { get; set; }
    public virtual ICollection<ModuleEntityHwVariantSignal_Plausibility_Mapping_ViewModel> ModuleEntityHwVariantSignal_Plausibility_Mapping { get; set; }
    public virtual ICollection<ModuleProperty_Attribute_ViewModel> ModuleProperty_Attribute { get; set; }
    public virtual ICollection<Plausibility_ViewModel> Plausibilities { get; set; }
    public virtual ICollection<Plausibility_Attribute_ViewModel> Plausibility_Attribute { get; set; }
    public virtual ICollection<Signal_Attribute_ViewModel> Signal_Attribute { get; set; }
    public virtual ICollection<Signal_DataType_Mapping_ViewModel> Signal_DataType_Mapping { get; set; }
    public virtual ICollection<Signal_ModuleEntity_Mapping_ViewModel> Signal_ModuleEntity_Mapping { get; set; }
    public virtual ICollection<Signal_ViewModel> Signals { get; set; }
    public virtual ICollection<Type_ViewModel> Types { get; set; }
    public virtual ICollection<GeneralParameter_ViewModel> GeneralParameters { get; set; }
    public virtual ICollection<Preferences_ViewModel> Preferences { get; set; }
    public virtual ICollection<IODPEntity_ViewModel> IODPEntities { get; set; }
    public virtual ICollection<ModuleEntity_IODPEntity_Mapping_ViewModel> ModuleEntity_IODPEntity_Mapping { get; set; }
    public virtual ICollection<Signal_IODPEntity_Mapping_ViewModel> Signal_IODPEntity_Mapping { get; set; }
    public virtual ICollection<ValidValue_ViewModel> ValidValues { get; set; }

    public virtual ICollection<ConfigSet_ViewModel> ConfigSets_LockedBy { get; set; }
    public virtual ICollection<ConfigSet_Attribute_ViewModel> ConfigSet_Attribute_LockedBy { get; set; }
    public virtual ICollection<ConfigSet_DataType_Mapping_ViewModel> ConfigSet_DataType_Mapping_LockedBy { get; set; }
    public virtual ICollection<ConfigSet_IODPEntity_Mapping_ViewModel> ConfigSet_IODPEntity_Mapping_LockedBy { get; set; }
    public virtual ICollection<DataType_ViewModel> DataTypes_LockedBy { get; set; }
    public virtual ICollection<Feature_ViewModel> Features_LockedBy { get; set; }
    public virtual ICollection<GeneralParameter_ViewModel> GeneralParameters_LockedBy { get; set; }
    public virtual ICollection<HwVariant_ViewModel> HwVariants_LockedBy { get; set; }
    public virtual ICollection<HwVariantConfigurationMapping_ViewModel> HwVariantConfigurationMappings_LockedBy { get; set; }
    public virtual ICollection<IODPEntity_ViewModel> IODPEntities_LockedBy { get; set; }

................

}
Andreea Elena
  • 29
  • 1
  • 7
  • You should change the signature of the method to allow for predicates on `T` because you want the predicate to translate into SQL. *Or* use `ProjectTo`, apply the `T1` predicate, and then do `ToList`. AM will do the predicate conversion. – Gert Arnold Mar 19 '21 at 16:02
  • Well, I cannot change the method signature since it use in several another function calls, but I'm interested in using ProjectTo, can you please show me an example. My find method was initially implemented like this : public List Find(Expression> predicate) { var listT1 = AutoMapperConfiguration.GetMapperConfiguration().Map>(_dbContext.Set().Where(q => !q.IsDeleted)); var result = listT1.Where(predicate.Compile()).ToList(); return result; } – Andreea Elena Mar 19 '21 at 16:39
  • Bit old, but [this](https://stackoverflow.com/a/12365931/861716) is the idea. – Gert Arnold Mar 19 '21 at 20:18
  • I've tried this like : public List Find(Expression> predicate) { return _dbContext.Set().ProjectTo().ToList(); } but it gives me an error like Missing map from T to T1 . and I don't know why is it necessary to createMap again since the mapping is in MapperProfile and it is executed at startup. – Andreea Elena Mar 19 '21 at 22:56
  • I also tried with return _dbContext.Set().Where(q => !q.IsDeleted).ProjectTo(AutoMapperConfiguration.GetMapperConfiguration()).Where(predicate).ToList(); but same error – Andreea Elena Mar 19 '21 at 23:18
  • Another try unsuccessful (now the app in in break mode )with _dbContext.Set().Where(q => !q.IsDeleted).ProjectTo(AutoMapperConfiguration.GetConfiguration()).Where(predicate).ToList(); and public static void Configure() { var config = new MapperConfiguration(cfg => cfg.AddProfile(new MapperProfile())); SetMapperConfiguration(config.CreateMapper()); SetConfiguration(config); } – Andreea Elena Mar 19 '21 at 23:34
  • Please [edit] your question if you have new information. – Gert Arnold Mar 20 '21 at 08:43

1 Answers1

2

You are using a quite old AutoMapper version, but the principle is similar with the latest versions (just the syntax may differ) - instead of Map which works client side you use AutoMapper Projection (in the version you use it is achieved with using ProjectTo extension method), which is basically generating Select operator transforming T to T1, but still keeping it IQueryable (the result is IQueryable<T1>), hence you could apply additional LINQ operators, including Where with Expression<Func<T1, bool>>.

So what you need is adding

using AutoMapper.QueryableExtensions;

and then, assuming your custom AutoMapperConfiguration.GetMapperConfiguration() method returns IMapper instance (due to Map method used in the posted code, so you'd better rename it to GetMapper to represent what it is returning), something like this (of course you can remove variables and just use return, I'm adding them for clarity):

var mapper = AutoMapperConfiguration.GetMapperConfiguration();
var query = _dbContext.Set<T>()
    // Here you have IQueryable<T>   
    .Where(q => !q.IsDeleted)
    .ProjectTo<T1>(mapper.ConfigurationProvider) // <-- note the usage of ConfigurationProvider property
    // Now you have IQueryable<T1>
    .Where(predicate);
var result = query.ToList();

And just in case the GetMapperConfiguration() returns MapperConfiguration instance (unlikely), pass it directly to the ProjectTo method

.ProjectTo<T1>(AutoMapperConfiguration.GetMapperConfiguration())

Regarding the update. Now when the original compilation issue is solved, you are experiencing Circular reference causing stack overflow with Automapper issue. Which means your view model classes contains circular refences, like ICollction<Child> Parent.Childen and Parent Child.Parent properties. The newer versions of the AutoMapper have different control over this issue, in your version you should either remove such back references from child to parent, or Ignore them in the map, or use MaxDepth(1) option when creating maps, e.g.

CreateMap<Parent, ParentViewModel>().MaxDepth(1);
CreateMap<Child, ChildViewModel>().MaxDepth(1);
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • I've tried your solution but in debug when it gets to the line var query = _dbContext.Set() // Here you have IQueryable .Where(q => !q.IsDeleted) .ProjectTo(mapper.ConfigurationProvider) // <-- note the usage of ConfigurationProvider property // Now you have IQueryable .Where(predicate); it gets Application break mode with the following error message System.StackOverflowException – Andreea Elena Mar 21 '21 at 08:37
  • I've edited my question with the code from automapper configuration class. I don't understand why it doesn't work . I'm using also using AutoMapper.QueryableExtensions; – Andreea Elena Mar 21 '21 at 08:39
  • The custom configuration class is just what I expected seeing the original code. Unfortunately from here there is nothing more we can do to help. It's not "my" solution, it is a standard AutoMapper solution, which I verified with your AutoMapper version just in case, and of course it is working. So probably there is something in the AutoMapper configuration or the model/view classes which is causing infinite recursion. Which can be identified only if having the that code. Or if you provide reproducible example. – Ivan Stoev Mar 21 '21 at 09:08
  • Actually I've reproduced it. See the update, the issue is well known for libraries like AutoMapper or JSON serialization with circular references in the object graph (EF6 and EF Core have no issues and handles them naturally). – Ivan Stoev Mar 21 '21 at 09:37
  • I have edited the question with info for all the AutoMapper configuration inside project and a snippet for view model class, just a small piece because it is huge. Can you please have a lock. – Andreea Elena Mar 21 '21 at 09:38
  • So if i update the Automapper version this issue shall be solved without updating the project implementation? If yes what version is best to use? – Andreea Elena Mar 21 '21 at 09:51
  • Just do what I'm suggesting in the update. Also I don't see any call to `IgnoreAllVirtual` method which would have probably solved the issue. But also you are configuring directly the inverse map (ViewModel-> Model), and `Ignore` or `MaxDepth` must be configured for Model->ViewModel map (used by `ProjectTo`) or both. That's it. Btw, SO rules do not allow changing the subject of the original question, which is solved by the original answer, so I'm updating it/commenting here only on goodwill. – Ivan Stoev Mar 21 '21 at 10:07
  • Regrading the AM version, I usually use the latest available :-) And yes, for instance the latest at this time AM 10.1.1 has no such issue by default and also the code should work w/o any change/additional modification. – Ivan Stoev Mar 21 '21 at 10:14
  • Thanks a lot for your time and answers, I will try to update all the create map instructions by adding MaxDepth(1) and I will get back with status. – Andreea Elena Mar 21 '21 at 10:31
  • I've set MaxDepth on all the createMap with Parent/Child but unfortunately now i the overflow exception is resolved but I have another one "Message = "Value cannot be null.\r\nParameter name: body"" :( – Andreea Elena Mar 21 '21 at 19:48
  • You seem to have a lot of usual stuff, don't you? In such case it would have been much easier if you just upgrade AutoMapper. I've did that from 4.2.1 (used to provide solution and then reproduce the SO issue) to 10.1.1 and it didn't require any code changes (compiles just fine and runs without issues). In general each version is improving. But requires retesting of course. – Ivan Stoev Mar 22 '21 at 06:33
  • Well yes, I have installed the new version 10.1.1, it seems that the only modification is that the Configure method from Profile class is no longer available and the profile configuration can be done through constructor. However now when I execute var query = _dbContext.Set().Where(q => !q.IsDeleted).ProjectTo(mapper.ConfigurationProvider) it is slow about 10 minutes and it is not finished :( – Andreea Elena Mar 22 '21 at 07:45
  • Yeah, issue after issue, all unrelated. Most probably now you are including too much data (all these collections). Try using View model with only properties needed, or use the AutoMapper explicit expansion feature (you can google that) and specify explicitly which properties to include in the projection. Etc. Having single huge model is no different than loading the whole huge entity class with navigation properties. As I said, AutoMapper `ProjectTo` is no more than automatic `Select` statement. If you include too many things in the `Select`, you'll get slow result. – Ivan Stoev Mar 22 '21 at 11:45