Automapper Expression mapping one property to many

江枫思渺然 提交于 2020-07-22 21:35:21

问题


I'm running a WebAPI,

Asp.Net Core 3.1
Automapper: 9.0
Automapper.Extensions.ExpressionMapping: 3.1

My LocaleDto PK is a composite key of 2 FK - LanguageCode and CountryCode

  public class LocaleDto 
    {
        [Key, ForeignKey(nameof(Language)), Column(Order = 0)]
        public string LanguageCode { get; set; }

        public LanguageDto Language { get; set; }

        [Key, ForeignKey(nameof(Country)), Column(Order = 1)]
        public string CountryCode { get; set; }

        public CountryDto Country { get; set; }
    }

I would like to map LocaleDto to LocaleViewModel, where Id is build based on the following pattern languageCode-CountryCode ie. en-GB

 public class LocaleViewModel 
    {
        public string Id {get;set;}
        public string LanguageCode { get; set; }
        public LanguageViewModel Language { get; set; }
        public string CountryCode { get; set; }
        public CountryViewModel Country { get; set; }
    }

The following mapping works just fine when I map one object to another using a static helper method:

  CreateMap<LocaleDto, LocaleViewModel>()
                    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => LocalisationHelper.ToLocaleCode(src.LanguageCode, src.CountryCode)));

            CreateMap<LocaleViewModel, LocaleDto>()
                    .ForMember(dest => dest.LanguageCode, src => src.MapFrom(x => x.LanguageCode))
                    .ForMember(dest => dest.CountryCode, src => src.MapFrom(x => x.CountryCode));
...
  public static string ToLocaleCode(string languageCode, string countryCode)
        {
            if (!string.IsNullOrEmpty(languageCode) && !string.IsNullOrEmpty(countryCode))
            {
                return $"{languageCode}-{countryCode}";
            }
            return null;
        }

But when I map the expression, the result is not understandable in LINQ to SQL, cause it contains the helper LocalisationHelper.ToLocaleCode.

Expression<Func<LocaleViewModel, bool>> filter = x => x.Id == "en-GB";
var entityFilter = mapper.MapExpression<Expression<Func<LocaleDto, bool>>>(filter);

Inspect of entityFilter:

 {Param_0 => (ToLocaleCode(Param_0.LanguageCode, Param_0.CountryCode) == "en-GB")}

Exception

     The LINQ expression 'DbSet<LocaleDto>
         .Where(l => LocalisationHelper.ToLocaleCode(
             languageCode: l.LanguageCode, 
             countryCode: l.CountryCode) == "en-GB")' could not be translated. Either rewrite the query in a form that can be translated,
     or switch to client evaluation explicitly by inserting a call to
     either AsEnumerable(), AsAsyncEnumerable(), ToList(), or
     ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for
     more information.

Is there a way to differently map those properties in Automapper so the result can be translated to SQL, without the need of switching to client evaluation?


回答1:


What if you tried instead of using a static function evaluate the expression directly

CreateMap<LocaleDto, LocaleViewModel>()
   .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.LanguageCode + "-" + src.CountryCode));



回答2:


The Where condition in your current linq is generated on the server, and your server does not define the LocalisationHelper.ToLocaleCode method, so this exception will occur.

To solve this problem, you only need to convert the DbSet<LocaleDto> to list or enumerable before the where condition(which has mentioned in the exception), so that the where condition can be guaranteed to run under the client condition.

Change your code as follow:

DbSet<LocaleDto>.ToList().Where(l => LocalisationHelper.ToLocaleCode(l.LanguageCode,l.CountryCode) == "en-GB")

Update

Here is the second method:

Func<LocaleDto, bool> IsMatch = (x) =>
            ((!string.IsNullOrEmpty(x.LanguageCode) && !string.IsNullOrEmpty(x.CountryCode))
            ? $"{x.LanguageCode}-{x.CountryCode}" : null) == "en-GB";

var query = DbSet<LocaleDto>.Where(IsMatch).ToList();

You can also refer to this .



来源:https://stackoverflow.com/questions/61392778/automapper-expression-mapping-one-property-to-many

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!