3
respostas

Salvar dados com o Entity Framework 6 Code First

Olá, estou usando o EF 6 e não estou conseguindo salvar depois que fiz relacionamentos nas tabelas.

Tenho um Usuário que pode ter muitas Compras, e a Compra só tem 1 Usuário. Uma Compra tem 1 CompraCategoria e uma CompraCategoria tem N Compras.

Minha Usuario.cs:

[Table("usuario")]
    public class Usuario
    {
        [Column("id")]
        [ScaffoldColumn(false)]
        public int Id { get; set; }

        [Column("nome")]
        [Required]
        [MaxLength(150, ErrorMessage = "Máximo de 150 caracteres!")]
        [MinLength(5, ErrorMessage = "Mínimo de 5 caracteres!")]
        public string Nome { get; set; }

        [Column("data_nascimento")]
        [Required]
        public DateTime DataNascimento { get; set; }

        [Column("email")]
        [Required(ErrorMessage = "O E-mail é obrigatório!")]
        [EmailAddress(ErrorMessage = "E-mail inválido!")]
        //[Remote("ValidaEmailUnico", "Usuario", ErrorMessage = "E-mail já cadastrado!")]
        public string Email { get; set; }

        [Column("senha")]
        [Required]
        [MinLength(6, ErrorMessage = "Senha deve conter no mínimo 6 dígitos!")]
        [MaxLength(15, ErrorMessage = "Senha pode ter no máximo 15 dígitos!")]
        public string Senha { get; set; }

        [Column("ativo")]
        [Required]
        public bool Ativo { get; set; }

        [Column("data_criacao")]
        [Required]
        [ScaffoldColumn(false)]
        public DateTime DataCriacao { get; set; }

        [Column("data_modificacao")]
        [ScaffoldColumn(false)]
        public DateTime DataModificacao { get; set; }

        public ICollection<Compra> Compras { get; set; }

Minha Compra.cs:

[Table("compra")]
    public class Compra
    {
        [Key]
        [ScaffoldColumn(false)]
        [Column("id")]
        public int Id { get; set; }

        [Column("compra_categoria_id")]
        [ScaffoldColumn(false)]
        public int CompraCategoriaId { get; set; }

        [Column("usuario_id")]
        [ScaffoldColumn(false)]
        public int UsuarioId { get; set; }

        [Required(ErrorMessage = "O título é obrigatório!")]
        [MaxLength(255, ErrorMessage = "Máximo de 255 caracteres!")]
        [DisplayName("Título")]
        [Column("titulo")]
        public string Titulo { get; set; }

        [Required(ErrorMessage = "A descrição é obrigatória!")]
        [MaxLength(255, ErrorMessage = "Máximo de 255 caractres!")]
        [DisplayName("Descrição")]
        [Column("descricao")]
        public string Descricao { get; set; }

        [Required(ErrorMessage = "Escolha uma das opções!")]
        [DisplayName("Produto ou Serviço?")]
        [Column("produto_servico")]
        // 1: produto, 2: serviço
        public int ProdutoServico { get; set; }

        [Required(ErrorMessage = "Escolha uma das opções!")]
        [DisplayName("Produto novo ou usado?")]
        [Column("novo_usado")]
        // 1: novo, 2: usado
        public int NovoUsuado { get; set; }

        [Column("ativo")]
        [Required]
        public bool Ativo { get; set; }

        [Column("data_criacao")]
        [Required]
        [ScaffoldColumn(false)]
        public DateTime DataCriacao { get; set; }

        [Column("data_modificacao")]
        [ScaffoldColumn(false)]
        public DateTime DataModificacao { get; set; }

        // Propriedades de navegação
        [ForeignKey("Id")]
        public virtual CompraCategoria CompraCategoria { get; set; }

        [ForeignKey("Id")]
        public virtual Usuario Usuario { get; set; }

Minhas Migrations:

public override void Up()
        {
            CreateTable(
                "dbo.usuario",
                c => new
                    {
                        id = c.Int(nullable: false, identity: true),
                        nome = c.String(nullable: false, maxLength: 150),
                        data_nascimento = c.DateTime(nullable: false),
                        email = c.String(nullable: false),
                        senha = c.String(nullable: false, maxLength: 15),
                        ativo = c.Boolean(nullable: false, defaultValue:true),
                        data_criacao = c.DateTime(nullable: false),
                        data_modificacao = c.DateTime(),
                    })
                .PrimaryKey(t => t.id);

        }
public override void Up ()
        {
            CreateTable(
                "dbo.compra_categoria",
                c => new
                {
                    id = c.Int(nullable: false, identity: true),
                    nome = c.String(nullable: false, maxLength: 255),
                    tipo = c.Int(nullable: false),
                    ativo = c.Boolean(nullable: false),
                    data_criacao = c.DateTime(nullable: false),
                    data_modificacao = c.DateTime(nullable: false),
                })
                .PrimaryKey(t => t.id);

            CreateTable(
                "dbo.compra",
                c => new
                {
                    id = c.Int(nullable: false),
                    compra_categoria_id = c.Int(nullable: false),
                    titulo = c.String(nullable: false, maxLength: 255),
                    descricao = c.String(nullable: false, maxLength: 255),
                    produto_servico = c.Int(nullable: false),
                    novo_usado = c.Int(nullable: false),
                    ativo = c.Boolean(nullable: false),
                    data_criacao = c.DateTime(nullable: false),
                    data_modificacao = c.DateTime(nullable: false),
                })
                .PrimaryKey(t => t.id)
                .ForeignKey("dbo.compra_categoria", t => t.id)
                .Index(t => t.id);

        }
public override void Up()
        {
            AddColumn("dbo.compra", "usuario_id", c => c.Int(nullable: false));
            AddForeignKey("dbo.compra", "id", "dbo.usuario", "id");
        }

Quando vou salvar, o minha Compra tem tudo preenchido, exceto o Id que é criado automaticamente e as propriedades Usuario e CompraCategoria.

As propriedades UsuarioId e CompraCategoriaId eu preenchi manual mesmo, o objeto Compra fica assim:

            compra.DataCriacao = DateTime.Now;
            compra.DataModificacao = DateTime.Now;
            compra.NovoUsuado = 1;
            compra.Ativo = true;
            compra.UsuarioId = 3;
            compra.ProdutoServico = 1;
            compra.CompraCategoriaId = 1;
            compra.Titulo = "Título teste";
            compra.Descricao = "descricao teste";

Como eu disse, só as 2 propriedades de navegação ficam null.

Recebo o seguinte erro ao tentar salvar:

{"A instrução INSERT conflitou com a restrição do FOREIGN KEY \"FK_dbo.compra_dbo.compra_categoria_id\". O conflito ocorreu no banco de dados \"quero_comprar\", tabela \"dbo.compra_categoria\", column 'id'.\r\nA instrução foi finalizada."}

Acredito que seja por conta do null nas propriedades de navegação, mas como faço pra inserir elas? tem que dar um new sempre que for salvar?

3 respostas

Olá, José Guilherme!

Quando você chama essa linha, espera-se que Compra Categoria já tenha uma linha com ID igual a 1:

compra.CompraCategoriaId = 1;

Será que sua CompraCategoria não está vazia? Você pode verificar se existe uma CompraCategoria com ID = 1?

Marcelo, sim, existe uma compraCategoria já cadastrada no banco.

Você pode mostrar um pequeno exemplo de como deveria ser esse save?

eu devo só setar o compraCategoriaId com um id existente na tabela compraCategoria, e o EF se vira pra linkar la no db?

Oi José

Definir o ID para uma entidade CompraCategoriaId já existente no banco de dados já seria suficiente. A CompraCategoria que está no seu banco em ID igual a 1?