Add Migration and update at runtime Entityframework

Asked

Viewed 841 times

5

I am developing an application and the need arose to add Migration and run the update at runtime.

I already have the whole part that loads the modules:

public class ClientContext : DbContext
{

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        LoadModulos();
        LoadMaps(modelBuilder);
    }

    public static void LoadMaps(DbModelBuilder modelBuilder)
    {
        IEnumerable<Type[]> assemblies = AppDomain.CurrentDomain
            .GetAssemblies()
            .Where(a => a.FullName.StartsWith("NCode.")
                && a.FullName.Contains(".EF")
                && !a.FullName.Contains("NCode.EF")
                && a.GetTypes().Any(t => t.Namespace != null && t.Namespace.EndsWith(".Map")))
            .Select(a => a.GetTypes().Where(t => t.Namespace != null && t.Namespace.EndsWith(".Map")).ToArray());

        foreach (var types in assemblies)
        {
            foreach (var t in types)
            {

                // Verifica se classe pai do tipo (t) é a EntityTypeConfiguration<>
                var entityTypeConfiguration = typeof(EntityTypeConfiguration<>);
                var baseType = t.BaseType;
                if (!baseType.IsGenericType 
                    && baseType.IsGenericTypeDefinition
                    && !(baseType.GetGenericTypeDefinition() == entityTypeConfiguration)) 
                {
                    continue;
                }


                // Tipo da entidade
                Type entityType = baseType.GetGenericArguments()[0];

                // Método Add da Configuration
                MethodInfo method = typeof(ConfigurationRegistrar).GetMethods()
                            .FirstOrDefault(x => x.Name == "Add" && x.GetGenericArguments()[0].ToString().Equals("TEntityType"));

                // Trasforma em um generic method passando o Tipo da Entidade
                MethodInfo genericMethod = method.MakeGenericMethod(new Type[] { entityType });

                // Cria a instancia do Map
                object map = (object)Activator.CreateInstance(t);

                try
                {
                    // Invoca o generic method passando a configurations a instancia do map 
                    genericMethod.Invoke(modelBuilder.Configurations, new object[] { map });
                }
                catch (Exception ex)
                {
                }

            }
        }
    }

    private void LoadModulos()
    {
        NCodeSection configSection = (NCodeSection)
           System.Configuration.ConfigurationManager.GetSection("NCode");

        foreach (NCodeModuloElement customAssembly in configSection.Modulos)
        {
            try { Assembly.Load("NCode." + customAssembly.Nome + ".Model"); }
            catch (Exception ex) { }
            try { Assembly.Load("NCode." + customAssembly.Nome + ".EF"); }
            catch (Exception ex) { }
        }
    }

    public ClientContext(string nameOrConnectionString)
        : base(nameOrConnectionString)
    {

    }

Does anyone have any idea how to do?

  • Looking for something similar for customer updates I found this article that exemplifies the use of Migrations in Runtime: https://romiller.com/2012/02/09/running-scripting-migrations-from-code/

1 answer

4


This idea doesn’t make much sense. Within the approach Code First, would only make sense if you were creating classes (Models) at runtime also, as well as contexts and the whole structure involved.

In short, there’s nothing you can do. Migrations can be executed using a Powershell command (Update-Database) or using a publication mechanism (Web Deploy). It is done so for structural reasons: a Migration at all times should accompany a structural change in its class set.

Still, if you really need to invest in an idea like this, I think Frameworks are being used in a way tremendously wrong. I suggest rethinking this part of your application.


EDIT

It was explained by comment that the idea is to build an application by modules. The problem is the approach. With this, it is assumed that ASP.NET MVC is modular, when it is not modular.

The natural way to make it work would be through Partial Classes. The context would have to be partial and all Model classes would be too. Now, how would the changes need to be made in Controllers? And in Views dependent? There is also an aggravating factor: the Migrations need to have a predefined order. How this would be done for modules?

The answer is: it wouldn’t be. It’s not possible. If the idea is to work by "modules", it is better to use the approach by areas. It does not influence the database: only on Controllers and Views. The context continues from the root of the application.


EDIT 2

The author of the question posed a code that could be feasible with a dynamic call to Migrations. The problem is that there would no longer be the standard Code First: would be a new pattern defined by the author of the question, in which all the Migrations is generated within the DLL.

Consequently, there are a number of errors that could occur, since much of what exists would not work, and several manual checks would have to be done to execute the configuration script properly.

Suppose now that the application has gained two modules, and then three more. If I only wanted to have the fourth module, it would not be possible. I would have to have all 4 first modules because the scheme of Migrations is incremental.

In other words, it would be a reinvention of the wheel.

  • But I will add classes at runtime!

  • @Ronaldoasevedo Why? What’s the point?

  • Like this we are developing system with modules, and wanted to make that when you put the dll of the dependency injection module it recognizes q has new entities generates the Migration and and makes the update to update the base.

  • Yes, and as I told you, it’s wrong. That’s not how it does. I’m going to improve the answer.

  • Okay, if that’s not so, you could give me a tip on how to proceed?

  • @Ronaldoasevedo See if the answer now clarifies more.

  • You made that clear, but I’ve already made it work! the dependencies and the mappings, just needed it to generate automatically, as if the module was installable! Note: I’m not working with the views yet, just architecture.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.