web-dev-qa-db-fra.com

Le contrôleur d'échafaudage ne fonctionne pas avec Visual Studio 2013 Update 3 et 4

Je ne parviens pas à échafauder un contrôleur (contrôleur MVC5 avec des vues utilisant Entity Framework) dans Visual studio 2013 (mises à jour 3 et 4). Le message d'erreur est ci-dessous:

Une erreur s'est produite lors de l'exécution du générateur de code sélectionné: 

A configuration for type 'Library.Morthwind.Models.Catgeory' has already been added. To reference the existing configuration use the Entity<T>() or ComplexType<T>() methods

J'ai créé les modèles en sélectionnant "Reverse Engineer Code First" dans le menu Outils "Entity Framework Power Tools Beta 4".

Des idées sur ce qui pourrait causer cette erreur?

42
SimonB

J'ai eu le même problème aujourd'hui. 

J'avais ajouté une configuration personnalisée pour l'une de mes classes Model afin d'ajouter une relation à l'aide de l'API fluide. Cela a été spécifié dans ma classe dbContext dans le remplacement OnModelCreating à l'aide de ce qui suit:

modelBuilder.Configurations.Add(new OrderConfiguration());

Commenter la ligne ci-dessus a permis à l'échafaudage Controller de fonctionner comme prévu.

VS 2013 update 2 a rencontré un problème et l’échafaudage a généré une erreur inutile, sans autre information. Dans la mise à jour 3 installée, elle fournissait juste assez de détails pour détecter le problème sous-jacent. 

Jeff.

39
Jeff

J'ai eu ce problème aussi. La solution de Jeff fonctionne dans certains cas. Mais au fur et à mesure que mon DbContext grandissait avec de plus en plus de modèles dont les clés devaient être mappées, je ne pouvais pas supprimer les méthodes Configurations.Add (), car j'obtiendrais alors des erreurs selon lesquelles EF ne pourrait pas trouver les clés primaires, etc. 

J'ai découvert qu'en changeant ma classe dérivée DBContext pour qu'elle utilise les propriétés IDbSet au lieu de DbSet, je pouvais générer les contrôleurs et les vues sans problème. Cependant, pour moi, ceci introduit un autre problème, IDbSet ne prend pas en charge les méthodes asynchrones.

Il semble que je puisse générer des contrôleurs non asynchrones avec des configurations en place ou des méthodes asynchrones sans classes de configuration.

Si vos propriétés de contexte sont de type DbSet, essayez de les remplacer par IDbSet. Si vous ne générez pas de méthodes de contrôleur async, cela peut fonctionner pour vous.

19
Brian Scott

J'ai également eu le même problème et modifier ma classe de contexte pour utiliser IDbSet m'a permis d'utiliser avec succès l'échafaudage pour créer un nouveau contrôleur. Mais comme je ne voulais pas abandonner les méthodes asynchrones, j'ai modifié le contexte pour utiliser DbSet et cela a fonctionné pour moi.

6
Gandyman

Voici comment j'ai résolu ce problème. J'ai Visual Studio 2013 Update 4.
J'utilise EF Power Tools . Mettez en commentaire l'ensemble du DbSet <...> Dans OnModelCreating, ne laissez que l'objet que vous échafaudez: modelBuilder.Configurations.Add (new SomeTableDataMap ());

Au bas de ma classe de contexte, j'ai remarqué que ceci avait été créé: public System.Data.Entity.DbSet SomeTableDatas {get; ensemble; }

Oh: je mets ça aussi dans mon constructeur mais c'est pour autre chose, this.Configuration.LazyLoadingEnabled = false;

Sérieusement, cela fonctionnait aujourd'hui, j'ai essayé toutes ces solutions. Rien ne fonctionnait pour la mise à jour 4. Je travaillais dans les mises à jour 2 et 3 avec les solutions précédentes. C'est la solution la plus récente pour le moment.

3
Luke G

Solution de contournement simple qui a fonctionné pour moi (après avoir essayé de nombreuses autres solutions suggérées ici et ailleurs en vain ...). 

Dans la boîte de dialogue d'échafaudage, je viens d'ajouter un nouveau DataContext, par exemple. TempContext. Tous les échafaudages ont fonctionné comme prévu et je pouvais alors simplement déplacer le code généré dans TempContext dans mon DbContext d'origine et renommer TempContext dans les contrôleurs générés en DbContext d'origine.

2
Richard Houltz

Plusieurs solutions de contournement ont déjà été publiées pour ce problème. Et dans ce commentaire, je vais essayer de fournir le problème sous-jacent pourquoi cela peut échouer. [Avec l'espoir de sensibiliser les gens à la cause fondamentale]

Supposons que vous ayez un DbContext (pour être spécifique, une classe enfant de DbContext) dans votre application et que vous essayez d'utiliser une classe de modèle (disons Model) et les contrôleurs/vues DbContext et d'échafaudage. 

Je suppose que DbContext n'avait pas de propriété "DbSet <Model> Models {get; set;}", mais le DbSet a néanmoins été ajouté à DbContext à l'aide du code de la méthode OnModelCreating.

Dans le cas ci-dessus, l’échafaudage essaie d’abord de détecter la propriété DbSet sur DbContext (par réflexion uniquement - de sorte que cela ne détecte pas si OnModelCreating a du code pour ajouter le DbSet) et qu’il ne l’est pas, il ajoute une propriété DbSet au DbContext et essaie ensuite de le faire. échafaudage utilisant ce DbContext, cependant lors de l’exécution de l’échafaudage, nous créons une instance de DbContext et nous appelons également OnModelCreating. À ce stade, l’échafaudage échoue car il existe plusieurs types DbSet ayant le même modèle dans DbContext configuré dans le code dans OnModelCreating).

[Cela se produit non seulement pour le modèle utilisé, mais également pour les modèles associés dans ce modèle, l'échafaudage ajoute les propriétés DbSet pour tous les modèles associés]

[De plus, on ne voit pas les DbSet ajoutés une fois que l'échafaudage est terminé car celui-ci annule les modifications si l'opération ne s'est pas terminée correctement. Comme Jeff l'a mentionné, le message d'erreur était médiocre au départ et a été amélioré pour donner un indice à l'utilisateur. mais ce n'est toujours pas très clair ce qui se passe]

Il s’agit d’un bogue de l’échafaudage. Pour contourner ce problème, la solution consiste à utiliser la propriété DbSet sur DbContext pour tous les modèles associés de votre classe de modèle au lieu de les configurer dans OnModelCreating.

1
pradeep

Aucune des réponses de ce poste n'a fonctionné pour moi. J'ai géré ce problème en créant une nouvelle classe de contexte via le bouton Plus dans la boîte de dialogue d'échafaudage Ajouter un contrôleur. Une fois que VS a créé le contrôleur et les vues, je supprime simplement la classe de contexte créée et modifie le code du contrôleur généré pour utiliser ma classe de contexte existante.

Important : Ce processus ajoutera une nouvelle chaîne de connexion pour le nouveau contexte, n'oubliez pas de le supprimer également.

0
Luty

Je l'ai résolu en ajoutant un try/catch sur le code à la fonction OnModelCreating à l'intérieur de la classe de contexte . Gardez simplement le base.OnModelCreating (modelBuilder); 

en dehors de votre essai/attraper

0
Anas Ghanem

le mien a été réparé comme ceci:

    public virtual DbSet<Category> Categories { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //--> EntityTypeConfiguration<Your Model Configuration>
        modelBuilder.Configurations.Add(new EntityTypeConfiguration<CategoryMapping>());  

        base.OnModelCreating(modelBuilder);
    }

N'oubliez pas Ctrl + Maj + B pour que votre code soit compilé (je ne suis pas sûr d'une solution unique, mais comme le mien appartient à un autre projet de la même solution, il devrait d'abord être compilé)

0
deadManN

Aucune des autres réponses n'a fonctionné pour moi. Ce que j'ai découvert, c'est que le problème ne se produisait que lors de l'échafaudage et de l'ajout de configurations à l'aide de l'API Fluent. Donc ce que j'ai fait était, au lieu d'avoir des fichiers séparés, chacun ayant une configuration d'entité comme celle-ci:

public class ApplicationUserMapConfiguration : EntityTypeConfiguration<ApplicationUserMap>
{
    public ApplicationUserMapConfiguration()
    {
        ToTable("ApplicationUserMap", "Users");
        HasKey(c => c.Id);
     }
}

Et puis en ajoutant cette configuration au DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Configurations.Add(new ApplicationUserMapConfiguration()); 
}

Je viens d'ajouter la configuration complète à l'intérieur du DbContext pour chaque entité:

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

        //ApplicationUser

        modelBuilder.Entity<ApplicationUser>().HasKey(c => c.Id);
        modelBuilder.Entity<ApplicationUser>().ToTable("ApplicationUser", "Usuario");

        //Other entities...
    }

Maintenant, je peux parfaitement échafauder. J'ai déjà soumis et publié sur le Mvc GitHub .

En outre, si un autre message d'erreur apparaît, vous dites: 

Une erreur s’est produite lors de l’exécution du générateur de code sélectionné: «Une exception a été générée par la cible d’un appel».

Vous devriez modifier votre constructeur DbContext pour:

public YourDbContext() : base("YourDbContext", throwIfV1Schema: false) { }
0
Hernan Demczuk

J'entendais une erreur différente lorsque j'essayais d'échafauder un contrôleur avec des actions et des vues CRUD. Dans mon cas, il disait:

"Une erreur s'est produite lors de l'exécution du générateur de code sélectionné. Instance d'objet Non définie sur une instance de l'objet."

Le problème était difficile à trouver: j'ai créé une table dans SQL Server mais j'ai oublié de définir le Primary Key pour la table. La définition du Primary key et la mise à jour du fichier .edmx d'Entity Framework ont ​​résolu le problème.

J'espère que ça aide.

0
Leniel Maccaferri