代码之家  ›  专栏  ›  技术社区  ›  Ingweland

使用IQueryable将具有导航属性的实体转换为DTO

  •  0
  • Ingweland  · 技术社区  · 8 年前

    假设我有以下实体和dto

    public class Country
    {
        public List<NameLocalized> NamesLocalized;
        public CountryData Data;
    }
    
    public class NameLocalized
    {
        public string Locale;
        public string Value;
    }
    
    public class CountryData
    {
        public int Population;
    }
    
    public class CountryDto
    {
        public String Name;
        public CountryDataDto Data;
    }
    
    public class CountryDataDto
    {
        public int Population;
    }
    

    我需要将Country转换为CountryDto(理想情况下,我希望对数据库进行一次查询)。我在关于Stackoverflow的其他问题中收到了一些建议,现在我可以完成这项任务,但只能部分完成。我对如何转换导航属性感到困惑( CountryData 在这种情况下)。有人建议我使用 LINQKit 但是不知道如何实现它。这是我只填充的代码 Name 财产,但不是 Data 导航属性。

    public static async Task<List<CountryDto>> ToDtosAsync(this IQueryable<Country> source, string locale)
    {
        if(source == null)
        {
            return null;
        }
    
        var result = await source
            .Select(src => new CountryDto
            {    
               Name = src.NamesLocalized.FirstOrDefault(n => n.Locale == locale).Name
            })
            .ToListAsync();
    
        return result; 
    }
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Community Mofi    7 年前

    This 答案给了我解决问题的暗示。您需要使用LINQKit和构建表达式来转换导航属性。

    public static Expression<Func<CountryData, CountryDataDto>> ConverterExpression = cd => new CountryDataDto
            {
                Population = cd.Population
            };
    
    public static async Task<List<CountryDto>> ToDtosAsync(this IQueryable<Country> source, string locale)
    {
        if(source == null)
        {
            return null;
        }
    
        var result = await source
            .AsExpandable
            .Select(src => new CountryDto
            {    
               Name = src.NamesLocalized.FirstOrDefault(n => n.Locale == locale).Name
               Data = ConverterExpression.Invoke(src.Data)
            })
            .ToListAsync();
    
        return result; 
    }