首页 > 解决方案 > EF - 使用 Seeding 类时不要增加 id 值

问题描述

我正在.net core 2.1.1 中开发一个项目,我正在使用 Postgree 12 数据库。

在我的项目中,我有一个播种类,在播种中创建的对象在我的数据库中正常创建,但是当我在执行播种后尝试在银行中创建记录时,出现 ID 违规错误。

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");
        }
    }

这里报告了同样的情况,但我没有成功找到解决方案。

有人知道我为什么会收到这个错误吗?

标签: postgresqlentity-frameworkasp.net-core

解决方案


Linha 的 ID 由 EF Core 自动发现并设置为自动递增键 - 这意味着数据库负责分配 ID 值。但是,在您的播种中,您是通过构造函数 (1, 2, 3) 自己分配 ID。PostgreSQL 不会更新自动增量值,因此您尝试插入的下一个 Linha 将获得一个自动生成的密钥 1,这与种子值冲突。

为了使这个工作,删除 Linha 的 id 构造函数并让它保持未初始化。这将使 PostgreSQL 也为您的种子值生成自动增量值,并且一切都应该工作。


推荐阅读