O tipo de entidade <type> não faz parte do modelo para o contexto atual

147

Estou entrando no Entity Framework, mas não tenho certeza se estou perdendo um ponto crítico na abordagem de primeiro código.

Estou usando um padrão de repositório genérico baseado no código de https://genericunitofworkandrepositories.codeplex.com/ e criei minhas entidades.

Mas quando tento acessar ou modificar a entidade, deparo com o seguinte:

System.InvalidOperationException: O tipo de entidade Estate não faz parte do modelo para o contexto atual.

Isso acontece quando estou tentando acessá-lo no meu repositório:

public virtual void Insert(TEntity entity)
{
    ((IObjectState)entity).ObjectState = ObjectState.Added;
    _dbSet.Attach(entity); // <-- The error occurs here
    _context.SyncObjectState(entity);
}

O banco de dados (./SQLEXPRESS) é criado perfeitamente, mas as entidades (tabelas) simplesmente não são criadas na inicialização.

Eu estou querendo saber se eu preciso definir explicitamente o mapeamento das entidades? A EF não pode fazer isso sozinha?

Minha entidade é:

public class Estate : EntityBase
{
    public int EstateId { get; set; }
    public string Name { get; set; }
} 

Meu contexto é o seguinte:

public partial class DimensionWebDbContext : DbContextBase // DbContextBase inherits DbContext
{
    public DimensionWebDbContext() :
        base("DimensionWebContext")
    {
        Database.SetInitializer<DimensionWebDbContext>(new CreateDatabaseIfNotExists<DimensionWebDbContext>());
        Configuration.ProxyCreationEnabled = false;
    }

    public new IDbSet<T> Set<T>() where T : class
    {
        return base.Set<T>();
    }

}

Existe algum motivo específico para esse erro ocorrer? Eu tentei habilitar migrações e habilitar migrações automáticas sem qualquer ajuda também.

janhartmann
fonte

Respostas:

143

Coloque isso na sua DbContextclasse personalizada :

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Estate>().ToTable("Estate");
}

Se suas tabelas não forem criadas na inicialização, é por isso. Você precisa informar o DbContext sobre eles na substituição do método OnModelCreating.

Você pode fazer mapeamentos personalizados por entidade aqui ou separá-los em EntityTypeConfiguration<T>classes separadas .

danludwig
fonte
1
Obrigado, Dan - isso corrige. Agora as tabelas são criadas. Não há outro caminho, a EF não pode fazer isso sozinha? Não posso simplesmente anotar a entidade com [ToTable ('Estates')]] ou algo assim?
janhartmann
3
Eu acho que isso pode funcionar sem substituir OnModelCreatingse suas entidades estiverem na mesma montagem que a sua DbContext. Eu nunca usei anotações de dados para entidades, portanto, não posso dizer com certeza. Você sempre pode digitalizar montagens no seu OnModelCreatingpara encontrar entidades em outras montagens e registrá-las automaticamente (que é o que o Tripod faz).
Danludwig
Ah, claro. Obrigado pela observação sobre a maneira de fazê-lo, fiz algo semelhante agora e parece funcionar muito bem. (também graças às suas extensões de reflexão em: github.com/danludwig/Layout3/blob/master/UCosmic.Domain/Api/… ). Agora só preciso encontrar assemblies de referências em vez de procurar no assembly GetType (). "var assembly = Assembly.Load (" Dimension.Web.Domain ");" não é bonito ;-)
janhartmann
Ou talvez apenas mova minha nova pasta / Mapping / para o meu projeto Impl em vez do meu domínio.
janhartmann
@meep ou danludwig. Você pode me dizer mais sobre o Tripod ou compartilhar um link para mim?
DkAngelito
73

Aparentemente, esse erro é muito genérico, pode ter várias razões. No meu caso, foi o seguinte: A cadeia de conexão (no Web.config) gerada pelo .edmxera inválida. Depois de quase um dia tentando de tudo, mudei a cadeia de conexão da cadeia EF para uma cadeia ADO.NET. Isso resolveu meu problema.

Por exemplo, a string EF se parece com isso:

<connectionStrings> 
  <add name="BlogContext"  
    connectionString="metadata=res://*/BloggingModel.csdl| 
                               res://*/BloggingModel.ssdl| 
                               res://*/BloggingModel.msl; 
                               provider=System.Data.SqlClient 
                               provider connection string= 
                               &quot;data source=(localdb)\v11.0; 
                               initial catalog=Blogging;
                               integrated security=True; 
                               multipleactiveresultsets=True;&quot;" 
     providerName="System.Data.EntityClient" /> 
</connectionStrings>

E a string ADO.NET fica assim:

<connectionStrings>
  <add name="BlogContext"  
        providerName="System.Data.SqlClient"  
        connectionString="Server=.\SQLEXPRESS;Database=Blogging;
        Integrated Security=True;"/> 
</connectionStrings>

Fonte: http://msdn.microsoft.com/nl-nl/data/jj556606.aspx

Christiaan Maks
fonte
17
Meu problema também estava na cadeia de conexão. Eu havia renomeado meu modelo de dados e reexecutado meus modelos t4, mas esqueci de atualizar os metadados (arquivos .csdl, .ssdl, .msl) na cadeia de conexão. Sua resposta me ajudou a perceber isso, então obrigado!
Vyskol
4
Se você estiver usando o modelo de identidade para autenticação, precisará de duas cadeias de conexão: uma, a "DefaultConnection", que você pode renomear ou não e colocar em seu ApplicationDbContext () público: base ("IdentityDbContext", throwIfV1Schema: false) {} Foi isso que desencadeou meu erro como o seu (eu tinha a corda EF lá). A segunda cadeia de conexão é aquela criada com a adição do EF usando o assistente e solicita parâmetros da cadeia de conexão. Espero que isso ajude alguém.
JustJohn
o mesmo aqui. incrivelmente frustrante
Nick Molyneux
1
Eu atualizo de EF 4.xpara EF 6. Eu tive que regenerar a seqüência de conexão para adicionar uma tabela ( DatabaseFirst). Eu não percebi que meu connectionstring no app.confige web.configeram diferentes. Uma vez que eu assumi a connectionstringpartir da app.config, ele começou a trabalhar.
DHFW 04/0418
16

Para mim, o problema era que eu não havia incluído a classe de entidade no meu conjunto de db dentro do contexto da estrutura da entidade.

public DbSet<ModelName> ModelName { get; set; }
Demodave
fonte
12

Você pode tentar remover a tabela do modelo e adicioná-la novamente. Você pode fazer isso visualmente, abrindo o arquivo .edmx no Gerenciador de Soluções.

Passos:

  1. Clique duas vezes no arquivo .edmx no Gerenciador de Soluções
  2. Clique com o botão direito do mouse na cabeça da tabela que você deseja remover e selecione "Excluir do modelo"
  3. Agora, novamente, clique com o botão direito do mouse na área de trabalho e selecione "Atualizar modelo do banco de dados .."
  4. Adicione a tabela novamente da lista de tabelas
  5. Limpe e construa a solução
Uma corrida
fonte
8
Não há .edmx no código EF primeiro.
Tuukka Haapaniemi
Eu dei um +1, porém, porque ele (ou alguém com esta questão) pode querer re-pensar fazer Code First e fazê-lo desta forma, em vez :)
vapcguy
9

O problema pode estar na cadeia de conexão. Verifique se a cadeia de conexão é do provedor SqlClient, sem nenhum material de metadados relacionado ao EntityFramework.

Shawn de Wet
fonte
Provavelmente isso era óbvio para muitos, mas esse acabou sendo o meu problema (sobre como misturar db-first com code-first). Agora eu posso parar de girar minhas rodas, muito obrigado!
precisa saber é o seguinte
3

Eu vi esse erro quando uma tabela existente no banco de dados não é mapeada adequadamente para um primeiro modelo de código. Especificamente, eu tinha um caractere (1) na tabela do banco de dados e um caractere em C #. Alterar o modelo para uma sequência resolveu o problema.

Daniel Leach
fonte
3

Meu problema foi resolvido com a atualização da parte dos metadados da cadeia de conexão. Aparentemente, ele estava apontando para a referência .csdl / .ssdl / .msl errada.

ragnarswanson
fonte
Isso aconteceu comigo também. Eu havia copiado a cadeia de conexão EF de outro lugar e não havia atualizado o nome do modelo nos metadados.
devC 13/05/19
2

Outra coisa a verificar com a cadeia de conexão - o nome do modelo. Eu estava usando dois modelos de entidade, o DB primeiro. Na configuração, copiei a conexão da entidade para uma, renomeei-a e alterei a parte da cadeia de conexão. O que não mudei foi o nome do modelo; portanto, enquanto o modelo de entidade foi gerado corretamente, quando o contexto foi iniciado, a EF procurava no modelo errado as entidades.

Parece óbvio, mas há quatro horas que eu não voltarei.

Eddie
fonte
2

Para mim, o problema era que eu usei o connection stringgerado pelo ADO.NetModel (.edmx). Alterar a cadeia de conexão resolveu meu problema.

FN90
fonte
1

Isso também pode ocorrer se você estiver usando um cache de modelo persistente desatualizado por um motivo ou outro. Se o seu contexto foi armazenado em cache em um arquivo EDMX em um sistema de arquivos (via DbConfiguration.SetModelStore), o OnModelCreating nunca será chamado, pois a versão em cache será usada. Como resultado, se uma entidade estiver ausente no seu armazenamento em cache, você receberá o erro acima, mesmo que a cadeia de conexão esteja correta, a tabela exista no banco de dados e a entidade esteja configurada corretamente no seu DbContext.

strickt01
fonte
1

A mensagem era bem clara, mas não a recebi no início ...

Estou trabalhando com dois contextos de banco de dados do Entity Framework sysContexte shardContextno mesmo método.

A entidade que eu modifiquei \ updated é de um contexto, mas tentei salvá-lo no outro contexto como este:

invite.uid = user.uid;

sysContext.Entry(invite).State = EntityState.Modified;

sysContext.SaveChanges(); // Got the exception here

mas a versão correta deve ser esta:

invite.uid = user.uid;

shardContext.Entry(invite).State = EntityState.Modified;

shardContext.SaveChanges();

Depois de passar a entidade para o contexto correto, esse erro desapareceu.

Leniel Maccaferri
fonte
0

Parece óbvio, mas verifique se você não está ignorando explicitamente o tipo:

modelBuilder.Ignore<MyType>();

emragins
fonte
0

O mapa da entidade (mesmo um vazio) adicionado à configuração fará com que o tipo de entidade faça parte do contexto. Tínhamos uma entidade sem relação com outras entidades que foi corrigida com um mapa vazio.

McFEA
fonte
0

se você estiver tentando primeiro o banco de dados, verifique se sua tabela possui chave primária

Mahmoud
fonte
0

O Visual Studio 2019 parece causar isso para mim. Corrigi-o gerando o modelo edmx novamente em 2017.

chinupson
fonte
0

Tenho o mesmo problema no Entity Framewrok e o resolvi sob as etapas:

1-Abra o Model.edmx 2-altere o local da tabela (para fazer alterações no arquivo cs) 3-salve-o

Espero te ajudar

Akbar Asghari
fonte
0

Exclua o arquivo .edmx e adicione-o novamente. Especialmente, se você atualizou o Entity Framework.

Roy Oliver
fonte
0

Eu estava enfrentando o mesmo problema com o EntityFrameworkCore tentando atualizar um intervalo de valores.

Essa abordagem não funcionou

  _dbSet.AttachRange(entity);
  _context.Entry(entity).State = EntityState.Modified;
   await _context.SaveChangesAsync().ConfigureAwait(false);

Depois de adicionar o método UpdateRange e remover a conexão e entrada, tudo funciona

  _dbSet.UpdateRange(entity);
  await _context.SaveChangesAsync().ConfigureAwait(false);
Okyam
fonte
0

Para mim, foi causado porque renomeei a classe de entidade. Quando o revirei, estava ok.

Iván Kollár
fonte
0

Pode ser estúpido, mas se você tiver esse erro em alguma tabela, não se esqueça de limpar seu projeto e reconstruir (isso pode economizar muito tempo)

LeBigCat
fonte
0

Eu tive isso

using (var context = new ATImporterContext(DBConnection))
{
    if (GetID(entity).Equals(0))
    {
        context.Set<T>().Add(entity);
    }
    else
    {
        int val = GetID(entity);
        var entry = GetEntryAsync(context, GetID(entity)).ConfigureAwait(false);
        context.Entry(entry).CurrentValues.SetValues(entity);

    }
    
    await context.SaveChangesAsync().ConfigureAwait(false);
}

Isso estava em um método assíncrono, mas eu esqueci de aguardar antes de GetEntryAsync e, por isso, recebi o mesmo erro ...

bifedefrango
fonte