Add migration and make update at runtime EntityFramework

5

I'm developing an application and the need to add migration and run the update at runtime.

I already have all the 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 it?

    
asked by anonymous 10.06.2015 / 03:31

1 answer

4

This idea does not make much sense. Within the Code First approach, it would only make sense if you were creating Models at runtime as well as contexts and the entire framework involved.

In summary, can not do . Migrations can be performed by using a PowerShell command ( Update-Database ) or by using a Web Deploy mechanism. It is done for structural reasons: a Migration always must accompany a structural change in its class set.

Still, if it's even necessary to invest in such an idea, I think the Frameworks are being used in a tremendously wrong way. 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.

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

The answer is: it would not. It's not possible. If the idea is to work by "modules", it is best to use the area approach . It does not affect the database: only in Controllers and Views . The context continues to come from the root of the application.

EDIT 2

The question originator put a code that could be doable with a dynamic Migrations call. The problem is that there would no longer be the Code First pattern: this would be a new pattern defined by the question author, where all the Migrations code 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 made 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 Migrations scheme is incremental.

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

    
10.06.2015 / 06:21