Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

Problema em Relacionamentos e Migrações

Como visto no vídeo: Comecei incluindo o Produto no modelBuilder, criei uma migração e rodei através do Update-Database a tabela foi criada. Quando fui incluir as outras entidades, deste jeito:

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Produto>()
                .HasKey(t => t.Id);

            modelBuilder.Entity<Pedido>()
                .HasKey(t => t.Id);
            modelBuilder.Entity<Pedido>()
                .HasMany(t => t.Itens)
                .WithOne(t => t.Pedido);
            modelBuilder.Entity<Pedido>()
                .HasOne(t => t.Cadastro)
                .WithOne(t => t.Pedido)
                .IsRequired();

            modelBuilder.Entity<ItemPedido>()
                .HasKey(t => t.Id);
            modelBuilder.Entity<ItemPedido>()
                .HasOne(t => t.Pedido);
            modelBuilder.Entity<ItemPedido>()
                .HasOne(t => t.Produto);

            modelBuilder.Entity<Cadastro>()
                .HasKey(t => t.Id);
            modelBuilder.Entity<Cadastro>()
                .HasOne(t => t.Pedido);

        }

Ao tentar rodar o comando Add-Migration Model, recebi a seguinte mensagem de erro:

The child/dependent side could not be determined for the one-to-one relationship between 'Pedido.Cadastro' and 'Cadastro.Pedido'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.

Alguém pode me ajudar?

9 respostas

Boa noite.

Tente deletar o banco de dados e refazer o processo. "Aparentemente o código está certo"

Ou nas próximas aulas ele ensina como criar ele automaticamente com o EnsureCreated ou Migrate.

Caso persista informe como está seu arquivo.

Startup.cs e o appsettings.json caso possa mostra-los.

E aí, cara?! Seguinte, acabei importando o projeto baixado e percebi que antes eu tinha criado uma solução AspNet Core MVC do zero com a versão do DotNet Core 2.1.1 e a Solução que eu baixei da Alura e importei é DotNet Core 2.0...

Mesmo assim gostaria de saber como resolve este problema na versão mais recente.

E ai.

Olha eu fiz esse curso recentemente e importei diversas aulas, pois tinha vezes que estava transito e então estudava no serviço, acho difícil ser um problema de compatibilidade, provavelmente algo se perdeu no processo quando ele criou o banco pela primeira vez.

Mas conte mais como vc realizou a importação? vc copiou os arquivos para o seu projeto ou apenas baixou e abriu a solução do projeto baixado?

Caso queira posso dar uma olhada no projeto e ver se falta algo, só disponibilizar ele no Github eu baixo e vejo.

Já estou estudando isso mesmo xD

Cara,

A primeira vez que eu fiz, eu criei uma solução MVC do zero e fui colocando os arquivos de _Recursos conforme a demanda.

A segunda vez, que funcionou perfeitamente, eu baixei o projeto e o abri no Visual Studio, fiz todos os procedimentos e funcionou.

A diferença de uma solução para outra foi a versão do SDK e, consequentemente, a versão das libsdentro dele.

Por isso que quero saber se tem alguma configuração extra na versão mais recente do framework para que o migrations funcionar quando tem um relacionamento de 1-para-1.

Acredito que não tenha nenhum problema, pois, como falei na abertura do tópico, a migração de Produto foi feita com sucesso, o problema foi o relacionamento one-to-one, o que me leva a crer que na versão mais recente precisa de uma configuração extra para este relacionamento. Como você tinha pedido anteriormente, seguem os arquivos.

appsettings.json:

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "Default": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=PrimeirosPassos;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
    }
}

Startup.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace PrimeirosPassosAspNetCore
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            string connectionString = Configuration.GetConnectionString("Default");

            services.AddDbContext<ApplicationContext>(options =>
                options.UseSqlServer(connectionString)
            );
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Pedido}/{action=Carrossel}/{id?}");
            });
        }
    }
}
solução!

Boa noite.

Realizei algumas alterações no código veja se funciona, aparentemente esse nova versão está reclamando de que tem que ser atribuído como chave estrangeira e não apenas em um relacionamento 1 para 1.

Não sei ao certo dizer o porque seu código não funcionou na versão 2.1 mas se jogar esse o código abaixo na 2.0 ele tbm vai funcionar.

; /

using CasaDoCodigo.Models;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CasaDoCodigo
{
    public class ApplicationContext : DbContext
    {
        public ApplicationContext(DbContextOptions options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Produto>().HasKey(t => t.Id);

            modelBuilder.Entity<Pedido>().HasKey(t => t.Id);
            modelBuilder.Entity<Pedido>().HasMany(t => t.Itens).WithOne(t => t.Pedido);

            //modelBuilder.Entity<Pedido>().HasOne(t => t.Cadastro).WithOne(t => t.Pedido).IsRequired();
            modelBuilder.Entity<Pedido>().HasOne(t => t.Cadastro).WithOne(t => t.Pedido).HasForeignKey<Pedido>(t => t.CadastroId).IsRequired();

            modelBuilder.Entity<ItemPedido>().HasKey(t => t.Id);
            modelBuilder.Entity<ItemPedido>().HasOne(t => t.Pedido);
            modelBuilder.Entity<ItemPedido>().HasOne(t => t.Produto);

            modelBuilder.Entity<Cadastro>().HasKey(t => t.Id);
            modelBuilder.Entity<Cadastro>().HasOne(t => t.Pedido);
        }
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;

namespace CasaDoCodigo.Models
{
    [DataContract]
    public abstract class BaseModel
    {
        [DataMember]
        public int Id { get; protected set; }
    }

    public class Produto : BaseModel
    {
        public Produto()
        {

        }

        [Required]
        public string Codigo { get; private set; }
        [Required]
        public string Nome { get; private set; }
        [Required]
        public decimal Preco { get; private set; }

        public Produto(string codigo, string nome, decimal preco)
        {
            this.Codigo = codigo;
            this.Nome = nome;
            this.Preco = preco;
        }
    }

    public class Cadastro : BaseModel
    {
        public Cadastro()
        {
        }

        public virtual Pedido Pedido { get; set; }
        [Required]
        public string Nome { get; set; } = "";
        [Required]
        public string Email { get; set; } = "";
        [Required]
        public string Telefone { get; set; } = "";
        [Required]
        public string Endereco { get; set; } = "";
        [Required]
        public string Complemento { get; set; } = "";
        [Required]
        public string Bairro { get; set; } = "";
        [Required]
        public string Municipio { get; set; } = "";
        [Required]
        public string UF { get; set; } = "";
        [Required]
        public string CEP { get; set; } = "";
    }

    [DataContract]
    public class ItemPedido : BaseModel
    {
        [Required]
        [DataMember]
        public Pedido Pedido { get; private set; }

        [Required]
        [DataMember]
        public Produto Produto { get; private set; }

        [Required]
        [DataMember]
        public int Quantidade { get; private set; }

        [Required]
        [DataMember]
        public decimal PrecoUnitario { get; private set; }

        [DataMember]
        public decimal Subtotal => Quantidade * PrecoUnitario;

        public ItemPedido()
        {

        }

        public ItemPedido(Pedido pedido, Produto produto, int quantidade, decimal precoUnitario)
        {
            Pedido = pedido;
            Produto = produto;
            Quantidade = quantidade;
            PrecoUnitario = precoUnitario;
        }

        internal void AtualizaQuantidade(int quantidade)
        {
            Quantidade = quantidade;
        }
    }

    public class Pedido : BaseModel
    {
        public Pedido()
        {
            Cadastro = new Cadastro();
            CadastroId = Cadastro.Id;
        }

        public Pedido(Cadastro cadastro)
        {
            Cadastro = cadastro;
            CadastroId = cadastro.Id;
        }

        public List<ItemPedido> Itens { get; private set; } = new List<ItemPedido>();
        [Required]
        public virtual Cadastro Cadastro { get; private set; }

        public int CadastroId { get; set; }
    }
}

Boa tarde, Muito obrigado, sanou a dúvida. Realmente este código acima funcionou! Apesar de eu ainda achar estranho.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software