Question

Je suis nouveau sur MVC et EF.Mon application est un simple code d'abord avec plusieurs classes POCO et un DBContext comme celui-ci :

   public class ExpDefContext : DbContext
   {
      public DbSet<Experiment> Experiments { get; set; }
      public DbSet<Research> Researches { get; set; }
      ...

Le problème:Je dois ajouter à mon modèle de données un ensemble d'entités dont le type est construit au moment de l'exécution à partir de l'entrée de l'utilisateur, ce qui signifie que je n'ai aucune idée de sa structure de données.

J'ai lu que la classe Dbset non générique est faite juste pour ça, j'ai donc ajouté au contexte :

    public DbSet Log { get; set; }

...et créé un constructeur pour le contexte qui accepte le type d'exécution et définit le nouveau Dbset :

        public ExpDefContext(Type LogRecType)
        {
            Log = Set(LogRecType);
        }

(le type est d'ailleurs construit à l'aide de Reflection.Emit).

Dans le contrôleur, je crée le type (nommé LogRec) et le transmets à une nouvelle instance DBContext.Ensuite, je crée une instance LogRec et j'essaie de l'ajouter à la base de données :

    Type LogRec;
    LogRec = LogTypeBuilder.Build(dbExpDef, _experimentID);
    var dbLog = new ExpDefContext(LogRec);
    var testRec = LogRec.GetConstructor(Type.EmptyTypes).Invoke(Type.EmptyTypes);
    dbLog.Log.Add(testRec);
    dbLog.SaveChanges();

et j'obtiens une exception du dbLog.Log.Add(testRec):

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

Qu'est-ce que je fais mal?Existe-t-il une meilleure façon de procéder (de préférence sans plonger trop profondément dans Entity Framework) ?

Merci

Était-ce utile?

La solution

Je soupçonne qu'EF ne reflète que le générique DbSet<T> propriétés dans votre dérivé DbContext et ignore tout non générique DbSet propriétés lorsque le modèle est créé en mémoire.

Cependant, une approche alternative pourrait consister à utiliser l'API Fluent dans OnModelCreating pour ajouter votre type dynamique en tant qu'entité au modèle.

Tout d'abord, vous pouvez ajouter un type au modèle uniquement lorsque le modèle est intégré en mémoire pour la première fois que votre AppDomain est chargé.(Un modèle n'est construit qu'une seule fois par AppDomain.) Si vous aviez un constructeur par défaut du contexte en plus du constructeur surchargé et que vous aviez créé et utilisé une instance de contexte à l'aide de ce constructeur par défaut, votre modèle aurait été construit avec uniquement les types statiques et vous ne pouvez plus utiliser le type dynamique comme entité tant que l'AppDomain existe.Cela entraînerait exactement l'exception que vous avez.

Un autre point à considérer est la création du schéma de base de données.Si votre type est inconnu au moment de la compilation, le schéma de la base de données est inconnu au moment de la compilation.Si le modèle change en raison d'un nouveau type lors de la prochaine exécution de votre application, vous devrez mettre à jour le schéma de la base de données d'une manière ou d'une autre, soit en recréant la base de données à partir de zéro, soit en définissant un initialiseur de base de données personnalisé qui supprime uniquement le LogRec tableau et crée un nouveau tableau selon la nouvelle disposition du LogRec taper.Ou peut-être que les migrations Code-First pourraient aider.

À propos de la solution possible avec Fluent API :

Retirer le DbSet et ajoutez un Type membre à la place du contexte et remplacez OnModelCreating:

public class ExpDefContext : DbContext
{
    private readonly Type _logRecType;

    public ExpDefContext(Type LogRecType)
    {
        _logRecType = LogRecType;
    }

    public DbSet<Experiment> Experiments { get; set; }
    public DbSet<Research> Researches { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
        entityMethod.MakeGenericMethod(_logRecType)
            .Invoke(modelBuilder, new object[] { });
    }        
}

DbModelBuilder n'a pas de non-générique Entity méthode, donc invocation dynamique du générique Entity<T> la méthode est nécessaire.

Le code ci-dessus dans OnModelCreating est le pendant dynamique de...

modelBuilder.Entity<LogRec>();

...qui serait utilisé avec un statique LogRec type et cela rend simplement le type en tant qu'entité connu d'EF.C'est exactement la même chose que d'ajouter un DbSet<LogRec> propriété à la classe de contexte.

Vous devriez pouvoir accéder à l'ensemble d'entités de l'entité dynamique en utilisant...

context.Set(LogRecType)

...qui renverra un message non générique DbSet.

Je ne sais pas si cela fonctionnera et je ne l'ai pas testé, mais l'idée vient de Rowan Miller, membre de l'équipe EF, donc j'ai un peu d'espoir que ce soit le cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top