繁体   English   中英

Automapper Expression 将一个属性映射到多个

[英]Automapper Expression mapping one property to many

我正在运行一个 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; }
    }

我想将 map LocaleDto 转换为 LocaleViewModel,其中Id是基于以下模式languageCode-CountryCode 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; }
    }

当我使用 static 辅助方法 map 一个 object 到另一个时,以下映射工作得很好:

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

但是当我使用 map 表达式时,在 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")}

例外

     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 中对这些属性进行不同的 map 以便结果可以转换为 SQL,而无需切换到客户端评估?

如果您尝试而不是使用 static function 直接评估表达式怎么办

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

你当前的 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();

你也可以参考这个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM