EF - не увеличивайте значение id при использовании класса Seeding - PullRequest
0 голосов
/ 09 мая 2020

Я разрабатываю проект в. net core 2.1.1 и использую базу данных Postgree 12.

В моем проекте у меня есть класс заполнения, и создаются объекты, созданные в процессе заполнения обычно в моей базе данных, но когда я пытаюсь создать запись в банке после выполнения заполнения, я получаю ошибку нарушения идентификатора.

PostgresException: 23505: повторяющееся значение ключа нарушает уникальное ограничение «PK_Linha»

это мой класс посева:

    public class SeedingService
    {
        //Populariza o BD

        private MesContext _context;

        public SeedingService(MesContext context)
        {
            _context = context;
        }

        public void Seed()
        {
            _context.Migrar();
            if ( _context.Linha.Any()) // este if serve para verificar se já existe dados no BD
            {
                // operação Any verifica se já existe algo na tabela x
                return; // se já existe retorna Obs: "O BD já foi populado"
            }

            Linha l1 = new Linha(1, "Linha 1", "descricao da linha1");
            Linha l2 = new Linha(2, "Linha 2", "descricao da linha2");
            Linha l3 = new Linha(3, "Linha 3", "descricao da linha3");


        // add os dados no BD
        _context.Linha.AddRange(l1,l2,l3);
            _context.SaveChanges();
        }
    }

это моя модель:

    public class Linha
    {
        public int Id { get; set; }
        [Required(ErrorMessage = "Campo {0} é obrigatório")] // {0} é o campo Name
        [StringLength(25, MinimumLength = 3,ErrorMessage = "O campo {0} deve ter entre {2} a {1} caracteres")]
        public string Nome { get; set; }
        [StringLength(200, MinimumLength = 5, ErrorMessage = "O campo {0} deve ter entre {2} a {1} caracteres")]
        [Display(Name = "Descrição")]
        public string Descricao { get; set; }

        public ICollection<Estoque> Estoques { get; set; } = new List<Estoque>();
        public ICollection<OrdemProducao> OrdensProducao { get; set; } = new List<OrdemProducao>();
        public ICollection<LinhaEquipamento> LinhaEquipamentos { get; set; } = new List<LinhaEquipamento>();

        public Linha()
        {
        }

        public Linha(int id, string nome, string descricao)
        {
            Id = id;
            Nome = nome;
            Descricao = descricao;
        }
    }

Это мой контроллер:

    public class LinhaController : Controller
    {
        private readonly LinhaService _context;
        private readonly UsuarioService _userContext;

        public LinhaController(LinhaService context, 
            UsuarioService userContext)
        {
            _context = context;
            _userContext = userContext;
        }

        public async Task<IActionResult> Index()
        {
            var idUser = Int32.Parse(User.FindFirst("IdUsuario")?.Value);
            if (!await _userContext.VerificaPermissao( // se ele n possui permissão
                idUser, "Perm_Linha", ""))
            {
                return RedirectToAction("SemPermissao", "Home", new { area = "" });
            }

            if (!await _userContext.VerificaPermissao( // se ele n possui permissão
                idUser, "Perm_Linha", "Sub_Deletar"))
            {
                ViewBag.PossuiDelete = false; // n possui
            }
            else
            {
                ViewBag.PossuiDelete = true; // possui
            }

            var list = await _context.FindAllAsync();
            return View(list);
        }

        //GET CREATE
        public async Task<IActionResult> Create()
        {
            var idUser = Int32.Parse(User.FindFirst("IdUsuario")?.Value);
            if (!await _userContext.VerificaPermissao( // se ele n possui permissão
                idUser, "Perm_Linha", "Sub_Criar"))
            {
                return StatusCode(403);
            }
            return View();
        }

        //POST CREATE
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(Linha obj)
        {
            /*verifica se post é valido. Se  o js estiver desabilitado no navegador do usuario
            ele consegue dar post vazio, esse if serve para previnir isso*/
            if (!ModelState.IsValid)
            {
                return View(obj);
            }

            if (await _context.VerificaNome(obj.Nome, -1)) // se existe login
            {
                return Json("Erro: Este Nome já existe.");
            }

            await _context.InsertAsync(obj);
            return Json("Success");
        }
    }

Об этой же ситуации сообщалось здесь , но мне не удалось найти решение для этого.

Кто-нибудь знает, почему я получаю эту ошибку?

1 Ответ

1 голос
/ 09 мая 2020

Идентификатор Linha автоматически обнаруживается EF Core и настраивается как автоматически увеличивающийся ключ - это означает, что база данных отвечает за присвоение значений идентификаторов. Однако при посеве вы сами назначаете идентификаторы через конструктор (1, 2, 3). PostgreSQL не обновляет значение автоинкремента, поэтому следующая Linha, которую вы попытаетесь вставить, получит автоматически сгенерированный ключ 1, который конфликтует с начальным значением.

Чтобы это сработало, удалите id конструктора Linha и оставьте его неинициализированным. Это заставит PostgreSQL генерировать значения автоинкремента для ваших засеянных значений, и все должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...