将来自DTO的数据添加到db

时间:2019-05-29 07:11:32

标签: c# entity-framework asp.net-web-api automapper dto

我有实体和相关的DTO,用于将数据从DB(实体框架6)传输到Web API的不同层。这是代码:

    public class Dish
    {
        public int DishId { get; set; }

        [Required]
        [Index(IsUnique = true)]
        [StringLength(400)]
        public string Name { get; set; }

        public string Description { get; set; }

        public double PreparationTime { get; set; }

        public string Photo { get; set; }

        public virtual ICollection<Category> Categories { get; set; } = new List<Category>();

        public virtual ICollection<Ingredient> Ingredients { get; set; } = new List<Ingredient>();

        public virtual ICollection<IngredientAmount> IngredientAmounts { get; set; } = new List<IngredientAmount>();

        public virtual ICollection<RecipeUnit> RecipeUnits { get; set; } = new List<RecipeUnit>();
    }
public class DishDetailedDTO: IDishDTO
    {
        public int DishId { get; set; }

        [Required]
        [StringLength(400)]
        public string Name { get; set; }

        public string Description { get; set; }

        public double PreparationTime { get; set; }

        public string Photo { get; set; }

        public List<CategoryDTO> Categories { get; set; }

        public List<IngredientDetailedDTO> Ingredients { get; set; }

        public List<IngredientAmountDTO> IngredientAmounts { get; set; }

        public List<RecipeUnitDTO> RecipeUnits { get; set; }

    }
public class Category
    {
        public int CategoryId { get; set; }

        [Required]
        [Index(IsUnique = true)]
        [StringLength(20)]
        public string Name { get; set; }

        public virtual ICollection<Dish> Dishes { get; set; } = new List<Dish>();
    }
    public class CategoryDTO: ICategoryDTO
    {
        public int CategoryId { get; set; }

        [Required]
        [StringLength(20)]
        public string Name { get; set; }
    }

当我尝试添加新的Dish对象时出现问题,该对象的导航属性(让我们说类别)在数据库中已经存在。通常,我从某个地方(前端)获得DishDTO,然后使用自动映射器将其映射到Dish,然后将此Dish添加到上下文中。这是小范围再现问题的地方:

        static void Main(string[] args)
        {
            Mapper.Initialize(x=> 
            {
                x.CreateMap<Dish, DishDTO>();
                x.CreateMap<Dish, DishDetailedDTO>();
                x.CreateMap<Dish, DishAvailableIngredientsDTO>();
                x.CreateMap<DishDTO, Dish>();
                x.CreateMap<DishDetailedDTO, Dish>();
                x.CreateMap<DishAvailableIngredientsDTO, Dish>();
                x.CreateMap<Category, CategoryDTO>();
                x.CreateMap<CategoryDTO, Category>();
                x.CreateMap<Ingredient, IngredientDetailedDTO>();
                x.CreateMap<Ingredient, IngredientDTO>();
                x.CreateMap<IngredientDTO, Ingredient>();
                x.CreateMap<IngredientDetailedDTO, Ingredient>();
                x.CreateMap<IngredientAmount, IngredientAmountDTO>();
                x.CreateMap<IngredientAmountDTO, IngredientAmount>();
                x.CreateMap<RecipeUnit, RecipeUnitDTO>();
                x.CreateMap<RecipeUnitDTO, RecipeUnit>();
            });

            var context = new EFDbContext();

            var dish = new DishDetailedDTO()
            {
                Name = "SomeName",
                Categories = new List<CategoryDTO>
                { 
                   new CategoryDTO()
                   {
                       Name = "Breakfast"
                   }
                }
            };

            context.Dishes.Add(Mapper.Map<Dish>(dish));
            context.SaveChanges();

            Console.ReadLine();

        }

然后我有例外

SqlException: Cannot insert duplicate key row in object 'dbo.Categories' with unique index 'IX_Name'. The duplicate key value is (Breakfast).
The statement has been terminated.

1 个答案:

答案 0 :(得分:0)

您的Dish模型的设计是错误的,一个Dish可以有多个Categories,而一个Category可以有多个Dishes许多关系。要处理这种情况,您需要添加其他模型,例如:-

public class DishCategoryMapping
{
    public int Id { get; set; }
    public int DishId { get; set; }
    public int CategoryId { get; set; }

    //navigation properties
}

然后您的盘子模型将变成

public class Dish
{
    public int DishId { get; set; }
    public virtual ICollection<DishCategoryMapping> DishCategoryMappings { get; set; }

    //other properties
}

然后,您将在DishCategoryMapping表中为菜肴的每个类别插入一行。