簡體   English   中英

如何使用 AutoMapper 將 DTO 展開為實體/對象屬性

[英]How to use AutoMapper to unflatten DTO to entity/object property

這可能是一個非常基本的問題,請原諒我對 AutoMapper 的無知。 我試圖從文檔和其他 SO 問題中找出答案,但到目前為止都失敗了。 也許我正在嘗試使用 AutoMapper 做一些我不應該做的事情。 我想從展平的 DTO 為對象屬性設置一個值。

鑒於這些;

public class Fruit
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ColourId { get; set; }
    public Colour Colour { get; set; }
}

public class Colour
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class FruitDto
{
    public string Name { get; set; }
    public string ColourName { get; set; }
}

我可以創建一個扁平的 DTO 沒問題,

var db = _serviceScopeFactory.CreateScope()
    .ServiceProvider.GetService<FruitDb>();
var fruitDtos = db.Fruits.ProjectTo<FruitDto>(_mapper.ConfigurationProvider);
foreach (var dto in fruitDtos)
{
    Console.WriteLine($"db fruit {dto.Name} = {dto.ColourName}");
}

但是當我嘗試從 DTO 映射回來時,我需要做什么來獲取水果對象顏色屬性集和 Colour.Name 集並不明顯。

var exampleDto = new FruitDto()
{
    Name = "lime",
    ColourName = "green"
};
var exampleFruit = _mapper.Map<FruitDto, Fruit>(exampleDto);
Console.WriteLine($"example fruit {exampleFruit.Name} = {exampleFruit.Colour?.Name}");

讓 AutoMapper 將 exampleFruit.Colour 設置為一個新的 Color 實例並設置 Name 屬性的正確方法是什么(這個問題的擴展,一旦設置,如果顏色已經存在,我應該如何設置 colour.Id 屬性?數據庫)?

這是上面片段的完整示例;

using System;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace EntityFrameworkAutomapConsole
{
    public class Fruit
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ColourId { get; set; }
        public Colour Colour { get; set; }
    }

    public class Colour
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class FruitDto
    {
        public string Name { get; set; }
        public string ColourName { get; set; }
    }

    class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddAutoMapper(typeof(AutoMapperProfile));
                    services.AddDbContext<FruitDb>(options =>
                    {
                        options.UseNpgsql("conn string here");
                    });
                    services.AddHostedService<Worker>();
                });
    }

    public class Worker : BackgroundService
    {
        private readonly IServiceScopeFactory _serviceScopeFactory;
        private readonly IMapper _mapper;

        public Worker(
            IServiceScopeFactory serviceScopeFactory,
            IMapper mapper)
        {
            _serviceScopeFactory = serviceScopeFactory;
            _mapper = mapper;

            var fruitDb = _serviceScopeFactory.CreateScope()
                .ServiceProvider.GetService<FruitDb>();
            fruitDb.Database.EnsureCreated();
        }

        protected override async Task ExecuteAsync(CancellationToken cancel)
        {
            var db = _serviceScopeFactory.CreateScope()
                .ServiceProvider.GetService<FruitDb>();
            var fruitDtos = db.Fruits.ProjectTo<FruitDto>(_mapper.ConfigurationProvider);
            foreach (var dto in fruitDtos)
            {
                Console.WriteLine($"db fruit {dto.Name} = {dto.ColourName}");
            }

            var exampleDto = new FruitDto()
            {
                Name = "lime",
                ColourName = "green"
            };
            var exampleFruit = _mapper.Map<FruitDto, Fruit>(exampleDto);
            Console.WriteLine($"example fruit {exampleFruit.Name} = {exampleFruit.Colour?.Name}");
        }
    }
   
    public class FruitDb : DbContext
    {
        public FruitDb(DbContextOptions options)
            : base(options)
        {
        }

        public DbSet<Fruit> Fruits { get; set; }
        public DbSet<Colour> Colours { get; set; }
        
        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.HasDefaultSchema("public");

            builder.Entity<Fruit>()
                .HasIndex(f => f.Id)
                .IsUnique();
            builder.Entity<Colour>()
                .HasIndex(c => c.Id)
                .IsUnique();

            base.OnModelCreating(builder);
        }
    }

    public class AutoMapperProfile : Profile
    {
        public AutoMapperProfile()
        {
            CreateMap<FruitDto, Fruit>();
            CreateMap<Fruit, FruitDto>();
        }
    }
}

感謝@lucian-bargaoanu,超級簡單的評論。 我在文檔中錯過了這一點。 所以我只需要在我的配置文件中使用 ReverseMap() 並刪除顯式FruitDtoFruit映射。

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<FruitDto, Fruit>();
        CreateMap<Fruit, FruitDto>();
    }
}

變成

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<Fruit, FruitDto>().ReverseMap();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM