Добавление в базу данных данных, полученных из DTO - PullRequest
0 голосов
/ 29 мая 2019

У меня есть сущности и связанные с ними DTO, которые используются для передачи данных из БД (Entity Framework 6) в разные уровни моего веб-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 откуда-то (внешний интерфейс), затем использую automapper, чтобы сопоставить его с блюдом, а затем добавить это блюдо в контекст.Вот воспроизведение проблемы в меньшем масштабе:

        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 голосов
/ 29 мая 2019

дизайн вашей 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.

...