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

如何使用AutoMapper映射配方和配料

  •  2
  • XardasLord  · 技术社区  · 7 年前

    我有以下RecipeModel、IngredientModel和RecipePartModel类,它们表示前端用户的DTO类:

    public class RecipeModel
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string ImageUrl { get; set; }
        public string Description { get; set; }
        public IEnumerable<RecipePartModel> RecipeParts { get; set; }
    }
    
    public class IngredientModel
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
    
    public class RecipePartModel
    {
        public Guid Id { get; set; }
        public IngredientModel Ingredient { get; set; }
        public string Unit { get; set; }
        public decimal Quantity { get; set; }
    }
    

    以下是我的实体类:

    public class Recipe : BaseEntity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string ImageUrl { get; set; }
        public string Description { get; set; }
        public virtual IEnumerable<RecipePart> RecipeParts { get; set; }
    }
    
    public class Ingredient : BaseEntity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public Guid Id { get; set; }
        public string Name { get; set; }
        public int Amount { get; set; }
        public virtual IEnumerable<RecipePart> RecipeParts { get; set; }
    }
    
    public class RecipePart : BaseEntity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public Guid Id { get; set; }
        public Ingredient Ingredient { get; set; }
        public Recipe Recipe { get; set; }
        public string Unit { get; set; }
        public decimal Quantity { get; set; }
    }
    

    我的问题是-如何使用AutoMapper将菜谱映射到RecipeModel?我试过这样的方法,但我认为它不好,因为它只是连接了整个数据库的所有RecipeParts,对吗?

    public class DomainProfile : Profile
    {
        public DomainProfile()
        {
            CreateMap<Ingredient, IngredientModel>().ReverseMap();
            CreateMap<Recipe, RecipeModel>()
                .ForMember(x => x.RecipeParts, opt => opt.MapFrom(src => src.RecipeParts));
        }
    }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Jamie Butterworth    7 年前

    要回答您关于如何使用AutoMapper将一个类型映射到另一个类型的问题,有很多方法。文件如下: http://docs.automapper.org/en/stable/Getting-started.html .

    我写了一个控制台应用程序,让它以我所知道的最快的方式使用你的代码工作。当我调试这个并检查recipeModel内部时,它引用了一个RecipePartModels列表和一个RecipePartModel。在RecipePartModel中,它引用了一个InCreditModel。

        static void Main(string[] args)
        {
            var profile = new DomainProfile();
    
            Mapper.Initialize(cfg => cfg.AddProfile(profile));
    
            var recipe = new Recipe
            {
                RecipeParts = new List<RecipePart>
                {
                    new RecipePart()
                    {
                        Ingredient = new Ingredient()
                    }
                }
            };
    
            var recipeModel = Mapper.Map<Recipe, RecipeModel>(recipe);
    
            Console.ReadKey();
        }
    

    要回答您对从数据库获取所有配方的担忧,如果您使用的是实体框架,则取决于是否启用了延迟加载。延迟加载确保从数据库中获取配方时,不会加载配方部分。只有当您稍后在程序流中直接访问配方部分时,才会加载它们。默认情况下启用了延迟加载,因此这是默认行为。如果你关闭它,你已经启用了急切加载加载加载所有配方部分,反过来他们的成分。

    这可能有助于: http://www.entityframeworktutorial.net/lazyloading-in-entity-framework.aspx .

        2
  •  1
  •   Jonas Høgh    7 年前

    这个映射没有什么不好的。事实上,您甚至不需要ForMember调用,因为这是默认约定。映射只需将实体子集合中的每个元素转换为相应的模型对象。

    当然,是否以有效的方式加载实体是另一回事。如果加载大量的Recipe实体,并延迟加载每个实体的RecipeParts集合,则会出现一个严重的“selectn+1”问题。但这不是汽车制造商的错。