Le type d'entité <type> ne fait pas partie du modèle pour le contexte actuel

147

J'entre dans Entity Framework, mais je ne sais pas si je manque un point critique dans l'approche code-first.

J'utilise un modèle de référentiel générique basé sur le code de https://genericunitofworkandrepositories.codeplex.com/ et j'ai créé mes entités.

Mais lorsque j'essaye d'accéder ou de modifier l'entité, je rencontre ce qui suit:

System.InvalidOperationException: le type d'entité Estate ne fait pas partie du modèle pour le contexte actuel.

Cela se produit lorsque j'essaye d'y accéder depuis mon référentiel:

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

La base de données (./SQLEXPRESS) est créée très bien, mais les entités (tables) ne sont tout simplement pas créées au démarrage.

Je me demande si j'ai besoin de définir explicitement le mappage des entités? EF n'est-il pas capable de le faire seul?

Mon entité est:

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

Mon contexte est le suivant:

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

}

Y a-t-il une raison spécifique pour laquelle cette erreur se produit? J'ai essayé d'activer les migrations et d'activer les migrations automatiques sans aucune aide non plus.

Janhartmann
la source

Réponses:

143

Mettez ceci dans votre DbContextclasse personnalisée :

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

Si vos tables ne sont pas créées au démarrage, c'est pourquoi. Vous devez en informer le DbContext dans le remplacement de méthode OnModelCreating.

Vous pouvez soit effectuer des mappages personnalisés par entité ici, soit les séparer en EntityTypeConfiguration<T>classes distinctes .

Danludwig
la source
1
Merci, Dan - cela résout le problème. Maintenant, les tables sont créées. Il n'y a pas d'autre solution, EF ne peut pas le faire seul? Je ne peux pas juste annoter l'entité avec [ToTable ('Estates')] ou quelque chose comme ça?
janhartmann
3
Je pense que cela pourrait fonctionner sans passer outre OnModelCreatingsi vos entités sont dans la même assemblée que la vôtre DbContext. Cependant, je n'ai jamais utilisé d'annotations de données pour les entités, donc je ne peux pas le dire avec certitude. Vous pouvez toujours scanner les assemblages dans votre OnModelCreatingpour trouver des entités dans d'autres assemblages et les enregistrer automatiquement (ce que fait Tripod).
danludwig
Ah, bien sûr. Merci pour la note sur la façon de faire Tripod, j'ai fait quelque chose de similaire maintenant, et cela semble fonctionner très bien. (également grâce à vos extensions de réflexion sur: github.com/danludwig/Layout3/blob/master/UCosmic.Domain/Api/… ). Maintenant, j'ai juste besoin qu'il trouve des assemblys de références au lieu de regarder l'assemblage GetType (). "var assembly = Assembly.Load (" Dimension.Web.Domain ");" is not pretty ;-)
janhartmann
Ou peut-être simplement déplacer mon nouveau dossier / Mapping / vers mon projet Impl au lieu de mon domaine.
janhartmann
@meep ou danludwig. Pouvez-vous m'en dire plus sur Tripod ou me partager un lien.
DkAngelito
73

Apparemment, cette erreur est très générique, elle pourrait avoir plusieurs raisons. Dans mon cas, c'était le suivant: La chaîne de connexion (dans Web.config) générée par le .edmxn'était pas valide. Après presque une journée à tout essayer, j'ai changé la chaîne de connexion de la chaîne EF à une chaîne ADO.NET. Cela a résolu mon problème.

Par exemple, la chaîne EF ressemble à quelque chose comme ceci:

<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>

Et la chaîne ADO.NET ressemble à ceci:

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

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

Christiaan Maks
la source
17
Mon problème était également dans la chaîne de connexion. J'avais renommé mon modèle de données et relancé mes modèles t4, mais j'avais oublié de mettre à jour les métadonnées (fichiers .csdl, .ssdl, .msl) dans la chaîne de connexion. Votre réponse m'a aidé à réaliser cela, alors merci!
Vyskol
4
Si vous utilisez le modèle d'identité pour l'authentification, vous avez besoin de 2 chaînes de connexion: une, la "DefaultConnection" que vous pouvez renommer ou non et mettre dans votre ApplicationDbContext (): base ("IdentityDbContext", throwIfV1Schema: false) {} C'est ce qui a déclenché mon erreur comme le vôtre (j'avais la chaîne EF là-dedans). La deuxième chaîne de connexion est celle créée à partir de l'ajout d'EF à l'aide de l'assistant et elle demande des paramètres de chaîne de connexion. J'espère que ça aidera quelqu'un.
JustJohn
pareil ici. incroyablement frustrant
Nick Molyneux
1
Je passe de EF 4.xà EF 6. J'ai dû régénérer la chaîne de connexion pour ajouter une table ( DatabaseFirst). Je n'ai pas remarqué que ma chaîne de connexion dans le app.configet le web.configétaient différents. Une fois que j'ai pris le relais connectionstringdu app.config, cela a commencé à fonctionner.
DHFW
16

Pour moi, le problème était que je n'avais pas inclus la classe d'entité dans mon ensemble de bases de données dans le contexte du cadre d'entité.

public DbSet<ModelName> ModelName { get; set; }
Démodave
la source
12

Vous pouvez essayer de supprimer la table du modèle et de l'ajouter à nouveau. Vous pouvez le faire visuellement en ouvrant le fichier .edmx à partir de l'Explorateur de solutions.

Pas:

  1. Double-cliquez sur le fichier .edmx dans l'Explorateur de solutions
  2. Faites un clic droit sur la tête de table que vous souhaitez supprimer et sélectionnez "Supprimer du modèle"
  3. Maintenant, cliquez à nouveau avec le bouton droit sur la zone de travail et sélectionnez "Mettre à jour le modèle à partir de la base de données."
  4. Ajouter à nouveau le tableau à partir de la liste des tableaux
  5. Nettoyez et construisez la solution
Arun
la source
8
Il n'y a pas de .edmx dans le code EF en premier.
Tuukka Haapaniemi
J'ai donné un +1, cependant, parce que lui (ou quelqu'un d'autre avec ce problème) pourrait vouloir repenser en faisant Code First et le faire de cette façon, à la place :)
vapcguy
9

Le problème peut être dans la chaîne de connexion. Assurez-vous que votre chaîne de connexion est destinée au fournisseur SqlClient, sans métadonnées liées à EntityFramework.

Shawn de Wet
la source
C'était probablement évident pour beaucoup, mais cela a fini par être mon problème (concernant le mélange de db-first avec code-first). Maintenant, je peux arrêter de faire tourner mes roues, grand merci!
Bonez024
3

J'ai vu cette erreur lorsqu'une table existante dans la base de données ne correspond pas correctement à un premier modèle de code. Plus précisément, j'avais un char (1) dans la table de la base de données et un char en C #. Le changement du modèle en chaîne a résolu le problème.

Daniel Leach
la source
3

Mon problème a été résolu en mettant à jour la partie métadonnées de la chaîne de connexion. Apparemment, il indiquait la mauvaise référence .csdl / .ssdl / .msl.

Ragnarswanson
la source
Cela m'est arrivé aussi. J'avais copié la chaîne de connexion EF ailleurs et je n'avais pas mis à jour le nom du modèle dans les métadonnées.
devC
2

Une autre chose à vérifier avec votre chaîne de connexion - le nom du modèle. J'utilisais deux modèles d'entité, DB d'abord. Dans la configuration, j'ai copié la connexion d'entité pour une, je l'ai renommée et j'ai changé la partie de la chaîne de connexion. Ce que je n'ai pas changé, c'est le nom du modèle, donc bien que le modèle d'entité soit généré correctement, lorsque le contexte a été lancé, EF recherchait dans le mauvais modèle les entités.

Cela semble évident, mais il y a quatre heures que je ne reviendrai pas.

Eddie
la source
2

Pour moi, le problème était que j'utilisais le fichier connection stringgénéré par ADO.NetModel (.edmx). La modification de la chaîne de connexion a résolu mon problème.

FN90
la source
1

Cela peut également se produire si vous utilisez un cache de modèle persistant qui est obsolète pour une raison ou une autre. Si votre contexte a été mis en cache dans un fichier EDMX sur un système de fichiers (via DbConfiguration.SetModelStore), OnModelCreating ne sera jamais appelé car la version mise en cache sera utilisée. Par conséquent, si une entité est manquante dans votre magasin mis en cache, vous obtiendrez l'erreur ci-dessus même si la chaîne de connexion est correcte, la table existe dans la base de données et l'entité est correctement configurée dans votre DbContext.

strickt01
la source
1

Le message était assez clair mais je ne l'ai pas compris au début ...

Je travaille avec deux contextes de base de données Entity Framework sysContextet shardContextdans la même méthode.

L'entité que j'avais modifiée \ mise à jour provient d'un contexte mais j'ai ensuite essayé de la sauvegarder dans l'autre contexte comme ceci:

invite.uid = user.uid;

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

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

mais la version correcte devrait être celle-ci:

invite.uid = user.uid;

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

shardContext.SaveChanges();

Après avoir passé l'entité au bon contexte, cette erreur a disparu.

Leniel Maccaferri
la source
0

Cela semble évident, mais assurez-vous de ne pas ignorer explicitement le type:

modelBuilder.Ignore<MyType>();

emragins
la source
0

la carte de l'entité (même vide) ajoutée à la configuration conduira à ce que le type d'entité fasse partie du contexte. Nous avions une entité sans relation avec d'autres entités qui a été fixée avec une carte vide.

mcfea
la source
0

si vous essayez d'abord DB, assurez-vous que votre table a une clé primaire

Mahmoud
la source
0

Visual Studio 2019 semble causer cela pour moi. Je l'ai corrigé en générant à nouveau le modèle edmx en 2017.

Chinupson
la source
0

J'ai le même problème dans Entity Framewrok et je l'ai résolu en suivant les étapes suivantes:

1-Ouvrez votre Model.edmx 2-changez un emplacement de table (pour faire le changement dans le fichier cs) 3-enregistrez-le

J'espère vous aider

Akbar Asghari
la source
0

Supprimez le fichier .edmx et ajoutez-le à nouveau. Surtout, si vous avez mis à niveau Entity Framework.

Roy Oliver
la source
0

J'étais confronté au même problème avec EntityFrameworkCore essayant de mettre à jour une plage de valeurs.

Cette approche n'a pas fonctionné

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

Après avoir ajouté la méthode UpdateRange et supprimé l'attachement et l'entrée, tout fonctionne

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

Pour moi, cela a été causé parce que j'ai renommé la classe d'entité. Quand je l'ai annulée, c'était OK.

Iván Kollár
la source
0

Cela pourrait être stupide, mais si vous ne rencontrez cette erreur que sur certaines tables, n'oubliez pas de nettoyer votre projet et de le reconstruire (cela pourrait vous faire gagner beaucoup de temps)

LeBigCat
la source
0

J'avais ça

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

C'était dans une méthode async, mais j'ai oublié de mettre await avant GetEntryAsync, et j'ai donc eu cette même erreur ...

bifedefrango
la source