将一个属性映射到多个属性的Automapper表达式

问题描述 投票:1回答:2

我正在运行WebAPI,

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

[我的LocaleDto PK是2 FK的复合键-LanguageCodeCountryCode

  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; }
    }

我想将LocaleDto映射到LocaleViewModel,其中Id是根据以下模式languageCode-CountryCode构建的。 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; }
    }

当我使用静态助手方法将一个对象映射到另一个对象时,以下映射工作正常:

  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;
        }

但是当我映射表达式时,结果在LINQ中无法理解为SQL,因为它包含帮助程序LocalisationHelper.ToLocaleCode。

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

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.

是否有一种方法可以在Automapper中以不同方式映射这些属性,以便可以将结果转换为SQL,而无需切换到客户端评估?

c# asp.net asp.net-core automapper
2个回答
1
投票
如果您尝试使用静态函数而不是静态函数,怎么办?

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


0
投票
您当前的linq中的Where条件已生成on the server,并且您的服务器未定义LocalisationHelper.ToLocaleCode方法,因此将发生此异常。

要解决此问题,您只需要在where条件之前(在异常中已提到)之前先输入convert the DbSet<LocaleDto> to list or enumerable,这样就可以保证where条件可以在the client condition下运行。

如下更改您的代码:

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

更新

这是第二种方法:

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();

您也可以参考this
© www.soinside.com 2019 - 2024. All rights reserved.