none
Erro EF com mensagem "has no key defined. Define the key for this EntityType" RRS feed

  • Pergunta

  • Pessoal estou fazer uma pequena aplicação em C# MVC3 com EF, e está dando o erro:

    One or more validation errors were detected during model generation:

    System.Data.Edm.EdmEntityType: : EntityType 'CNAES' has no key defined. Define the key for this EntityType.
    System.Data.Edm.EdmEntitySet: EntityType: EntitySet ?CNAES? is based on type ?CNAES? that has no keys defined.

    O model está abaixo:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace ERP.Models
    {
        public class CNAES
        {
            public int CNAEID { get; set; }
            public string Descricao { get; set; }
        }
    }

    Controler

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using ERP.Models;
    
    namespace ERP.Controllers
    {
        public class CNAESController : Controller
        {
            //
            // GET: /CNAES/
    
            private ERPCodeFirstContext db = new ERPCodeFirstContext();
    
            public ActionResult Index()
            {
                return View(db.CNAES.ToList());
            }
    
        }
    }
    

    View

    @model IEnumerable<ERP.Models.CNAES>
               
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    @foreach (var item in Model)
    {
        @Html.DisplayFor(modelItem => item.Descricao) <br/>
    }

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 11:30

Respostas

  • Olá Marlon,

    Adicione o DataAnnotation Key.

       public class CNAES
        {
            [Key]
            public int CNAEID { get; set; }
            public string Descricao { get; set; }
        }

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 12:04
    Moderador
  • Olá Marlon,

    Se vc já tem a base de dados criada, então vc tem que fazer assim:

    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
    
            public ERPCodeFirstContext()
            {
                    Database.SetInitializer(null);
            }
        }
    }

    E tb não pode utilizar o DropCreateDatabaseIfModelChanges, como estava antes no seu Global.asax.

    []s!



    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique


    sexta-feira, 1 de junho de 2012 14:54
    Moderador
  • Olá Fernando, 

    consegui fazer funcioanr desta maneira, conforme código abaixo:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    
    
    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
    
            public ERPCodeFirstContext()
            {
                Database.SetInitializer<ERPCodeFirstContext>(null);            
            }       
        }
    }

    Vi que no seu blog tem este assunto na url clique aqui

    Tá certo da maneira acima como coloquei?

    Abs...


    Marlon Tiedt
    www.sesmt.com.br

    • Marcado como Resposta Marlon Tiedt sexta-feira, 1 de junho de 2012 17:44
    sexta-feira, 1 de junho de 2012 16:49

Todas as Respostas

  • Olá Marlon,

    Adicione o DataAnnotation Key.

       public class CNAES
        {
            [Key]
            public int CNAEID { get; set; }
            public string Descricao { get; set; }
        }

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 12:04
    Moderador
  • Tks Fernando...

    Agora somente não aparece os dados. :) Tentando ver o que está acontecendo.
    Minha view está assim:

    @model IEnumerable<ERP.Models.CNAES>
    
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Marca</h2>
    
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table>
        <tr>
            <th>
                Nome
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Descricao)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.CNAEID }) |
                @Html.ActionLink("Details", "Details", new { id = item.CNAEID }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.CNAEID })
            </td>
        </tr>
    }
    
    </table>
    


    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 12:45
  • Olá Marlon,

    Neste caso acho melhor criar uma Thread no fórum de ASP.Net MVC.

    Mas vc consegue ver se os dados estão sendo retornados da base de dados?

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 12:50
    Moderador
  • Fernando, descobri o problema.

    No Global.asax tenho o código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using System.Data.Entity;
    using ERP.Models;
    
    namespace ERP
    {
        // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
        // visit http://go.microsoft.com/?LinkId=9394801
    
        public class MvcApplication : System.Web.HttpApplication
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
            }
    
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    "Default", // Route name
                    "{controller}/{action}/{id}", // URL with parameters
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
                );
    
            }
    
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
    
                Database.SetInitializer<ERPCodeFirstContext>(new DropCreateDatabaseIfModelChanges<ERPCodeFirstContext>());
            }
    
        }
    }

    O problema era que tinha dado outro nome para a conexão no Web.config

    Estava assim:

      <connectionStrings>        
        <add name="ERP" connectionString="Data Source=E020\SQLEXPRESS;Initial Catalog=SESMT;User ID=automa; Password=automa" providerName="System.Data.SqlClient"/>
      </connectionStrings>  
    

    E deveria ser assim:

      <connectionStrings>        
        <add name="ERPCodeFirstContext" connectionString="Data Source=E020\SQLEXPRESS;Initial Catalog=SESMT;User ID=automa; Password=automa" providerName="System.Data.SqlClient"/>
      </connectionStrings>  
    

    Agora parece que ele conecta e tenta buscar os dados.
    Porém agora tem o erro:

    Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.

    Erro está aqui:

    Line 17:         public ActionResult Index()
    Line 18:         {
    Line 19:             return View(db.CNAES.ToList());
    Line 20:         }
    Line 21: 

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 13:04
  • Olá Marlon,

    No seu Datacontext vc tem a linha abaixo? Se não, poste o código do seu DataContext.

    modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 13:10
    Moderador
  • Olá Fernando, 

    Como não sei aonde está isto estou postando o código abaixo do DBContext:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    
    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
        }
    }

    Subi aqui o projeto completo.

    http://www.sesmt.com.br/ERP.rar

    Abs


    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 13:18
  • Olá Marlon,

    No seu caso recomendo fazer o seguinte:

    1 - Remover a linha "Database.SetInitializer<ERPCodeFirstContext>(new DropCreateDatabaseIfModelChanges<ERPCodeFirstContext>());" do StartUp do seu projeto

    2 - Substituir seu contexto por:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    
    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
    
            public ERPCodeFirstContext()
            {
                if (Database.Exists())
                    Database.SetInitializer(new DropCreateDatabaseAlways<ERPCodeFirstContext>());
                else
                    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ERPCodeFirstContext>());
            }
        }
    }

    Vamos testar desta forma...

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 13:52
    Moderador
  • Fernando, estou achando que o problema está na conexão. Eu já tenho a base criada e não gostaria que o sistema mexe-se nisto.

    O erro que retorna agora é: CREATE DATABASE permission denied in database 'master'.

    Além disto o código dropou base inteira.

    Abs

    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 14:52
  • sexta-feira, 1 de junho de 2012 14:54
  • Olá Marlon,

    Se vc já tem a base de dados criada, então vc tem que fazer assim:

    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
    
            public ERPCodeFirstContext()
            {
                    Database.SetInitializer(null);
            }
        }
    }

    E tb não pode utilizar o DropCreateDatabaseIfModelChanges, como estava antes no seu Global.asax.

    []s!



    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique


    sexta-feira, 1 de junho de 2012 14:54
    Moderador
  • Olá Fernando, 

    consegui fazer funcioanr desta maneira, conforme código abaixo:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    
    
    namespace ERP.Models
    {
        public class ERPCodeFirstContext : DbContext
        {
            public DbSet<CNAES> CNAES { get; set; }
    
            public ERPCodeFirstContext()
            {
                Database.SetInitializer<ERPCodeFirstContext>(null);            
            }       
        }
    }

    Vi que no seu blog tem este assunto na url clique aqui

    Tá certo da maneira acima como coloquei?

    Abs...


    Marlon Tiedt
    www.sesmt.com.br

    • Marcado como Resposta Marlon Tiedt sexta-feira, 1 de junho de 2012 17:44
    sexta-feira, 1 de junho de 2012 16:49
  • Sim, esta perfeito.

    Desta forma vc esta correto, é este o modo como vc deve fazer quando não quer que o EF crie a base de dados para vc.

    Eu queria dizer justamente isso no post anterior, mas não prestei atenção e fiz besteira.

    Mas assim esta ok, desta forma o EF entende que vc não quer criar a base de dados automaticamente, e sim respeitar a base que ja existe.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 16:51
    Moderador
  • Valeu Fernando...

    Agora meu próximo passo é colocar Fluent Api na meu exemplo prático.

    Abs.

    Marlon Tiedt
    www.sesmt.com.br

    sexta-feira, 1 de junho de 2012 17:42
  • Olá Marlon,

    Vou marcar a resposta com o atributo Key como resposta, pois ela efetivamente é a resposta para sua pergunta inicial.

    Isso vai ajudar os próximos leitores.

    []s!


    Fernando Henrique Inocêncio Borba Ferreira
    while(alive){ this.WriteCode(); }
    Blog: http://ferhenriquef.com/
    Twitter: @ferhenrique

    sexta-feira, 1 de junho de 2012 17:51
    Moderador