我有以下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));
}
}
答案 0 :(得分:1)
此映射没有什么不好的。实际上,您甚至不需要ForMember调用,因为这是默认约定。映射将简单地将实体子集合中的每个元素转换为相应的模型对象。
当然,是否以有效的方式加载实体是另一回事。如果您加载大量的Recipe实体,而懒惰地为每个实体加载RecipeParts集合,则将遇到主要的“ SELECT N + 1”问题。但这不是AutoMapper的错。
答案 1 :(得分:1)
要回答有关如何使用AutoMapper将一个类型映射到另一个类型的问题,有很多方法可以这样做。文档在这里:http://docs.automapper.org/en/stable/Getting-started.html。
我编写了一个控制台应用程序,并使用您的代码以最快的方式使它运行。当我调试此代码并检查recipeModel内部时,它使用单个RecipePartModel引用了RecipePartModels列表。在该RecipePartModel中,它引用了IngredientModel。
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();
}
要回答有关从数据库获取所有配方的问题,如果使用的是Entity Framework,则取决于是否打开了延迟加载。延迟加载可确保从数据库中获取配方时,配方部分不会被加载。仅当您稍后在程序流中直接访问配方零件时,才会加载它们。默认情况下,延迟加载是打开的,因此这是默认行为。如果您将其关闭,则启用了预先加载功能,可以加载所有配方部分并依次加载其成分。
这可能会有所帮助:http://www.entityframeworktutorial.net/lazyloading-in-entity-framework.aspx。