Я пытаюсь внедрить Entity-Framework в свой проект! Мой проект основан на плагинах, поэтому я не знаю, какой объект мне нужно сохранить в базе данных.

Я реализовал это так:

public class DatabaseContext : DbContext
{
    public DatabaseContext() : base()
    {
        Database.Initialize(true);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        foreach( PluginDto plugin in BackendContext.Current.PluginManager._plugins) {
            foreach(Type obj in plugin.plugin.getPluginDatabaseObjects())
            {
                Type typ = typeof(EntityTypeConfiguration<>).MakeGenericType(obj);

                List<MethodInfo> l = modelBuilder.GetType().GetMethods().ToList<MethodInfo>();

                MethodInfo m_Entitiy = modelBuilder.GetType().GetMethod("Entity").MakeGenericMethod(new Type[] { obj });
                var configObj = m_Entitiy.Invoke(modelBuilder, null);

                MethodInfo m_ToTable = configObj.GetType().GetMethod("ToTable", new Type[] { typeof(String) });
                m_ToTable.Invoke(configObj, new object [] { obj.Name }); 
            }
        }

        base.OnModelCreating(modelBuilder);
    }

}

Но я получаю это исключение, когда даю сдачу:

Модель, поддерживающая контекст DatabaseContext, изменилась с момента база данных создана. Рассмотрите возможность использования Code First Migrations для обновления база данных (http://go.microsoft.com/fwlink/?LinkId=238269).

Эта ошибка вполне логична. База данных не синхронизирована, но как я получу обновление? Я что-то читал об этом:

 var config = new DbMigrationsConfiguration<MyContext> { AutomaticMigrationsEnabled = true };
 var migrator = new DbMigrator(config);
 migrator.Update();

Но я не знаю, как и где правильно его использовать! Большое спасибо!

EDIT1: Когда я пытаюсь: Enable-Migrations –EnableAutomaticMigrations

У меня такая ошибка:

System.NullReferenceException: Object reference not set to an instance of an object.
   at SOM.Backend.database.DatabaseContext.OnModelCreating(DbModelBuilder modelBuilder) in C:\Users\Flo\Documents\Visual Studio 2015\Projects\SOM\Backend\BackendService\BackendService\database\DatabaseContext.cs:line 26
   at System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder()
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.LazyInternalContext.MarkDatabaseInitialized()
   at System.Data.Entity.Database.Initialize(Boolean force)
   at SOM.Backend.database.DatabaseContext..ctor() in C:\Users\Flo\Documents\Visual Studio 2015\Projects\SOM\Backend\BackendService\BackendService\database\DatabaseContext.cs:line 21
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Data.Entity.Infrastructure.DbContextInfo.CreateInstance()
   at System.Data.Entity.Infrastructure.DbContextInfo..ctor(Type contextType, DbProviderInfo modelProviderInfo, AppConfig config, DbConnectionInfo connectionInfo, Func`1 resolver)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldInitialCreate(String language, String rootNamespace)
   at System.Data.Entity.Migrations.EnableMigrationsCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

EDIT2 :

  <connectionStrings>
    <add name="DatabaseContext" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=SOM_db.sdf;Max Database Size=1024" />
  </connectionStrings>
11
Flo 6 Сен 2016 в 15:01

4 ответа

Лучший ответ

То, о чем вы просите, выполнимо, но с некоторыми ограничениями.

Решение:

Сначала удалите

Database.Initialize(true);

Из конструктора. Конструктор вызывается несколько раз, включая миграции.

Во-вторых, создайте такой класс конфигурации

internal sealed class DataContextConfiguration : DbMigrationsConfiguration<DataContext>
{
    public DataContextConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
        ContextKey = "DataContext";
    }
}

Затем измените конструктор следующим образом:

public DataContext()
{
    Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, DataContextConfiguration>());
}

И все готово. Таблицы базы данных для типов сущностей из плагинов будут автоматически созданы / обновлены соответственно.

Напомним, что в основном это стандартный подход Code First с включенными автоматическими миграциями, но с динамической регистрацией / конфигурацией типа сущности из переопределения OnModelCreating.

Ограничения:

  • Если вы не установите AutomaticMigrationDataLossAllowed = true, когда существующий плагин будет удален, EF сгенерирует исключение, потому что ему не разрешено удалять соответствующие таблицы. И если вы это сделаете, таблицы плагинов будут удалены, поэтому, если плагин будет добавлен снова, он начнется с нуля.

  • Сущности плагина можно настроить только с помощью аннотаций к данным. Если вы хотите предоставить им полный контроль, вам, вероятно, потребуется изменить интерфейс плагина и вместо того, чтобы брать типы сущностей, вызвать какой-либо метод и передать вместо него DbModelBuilder, чтобы они могли использовать Fluent API для настройки своих сами типы сущностей.

11
Ivan Stoev 15 Сен 2016 в 12:11

Бегать:

Update-Database –Verbose

Если это не удалось, вставьте сообщения в качестве комментария.

1
Eduardo 14 Сен 2016 в 20:15
public class myContext : DbContext
{
    public DbSet<myTable> myTables { get; set; }

    public myContext() : base("myConStr") { }

    public void UpdateDatabase()
    {
        var Migrator = new DbMigrator(new Migrations.Configuration(){ TargetDatabase = new DbConnectionInfo(this.Database.Connection.ConnectionString, "System.Data.SqlClient") });
        IEnumerable<string> PendingMigrations = Migrator.GetPendingMigrations();
        foreach (var Migration in PendingMigrations)
            Migrator.Update(Migration);
    }
}

static void Main(string[] args)
{
   var db = new myContext();
   db.UpdateDatabase();
}
1
Serdar Didan 3 Окт 2018 в 22:36

Не думаю, что при таком подходе он когда-нибудь будет работать с EF6.

EF необходимо, чтобы DbSets находились в классе контекста, поэтому вам нужно на лету сгенерировать свой класс DatabaseContext (на основе сущностей плагина), скомпилировать и загрузить его. После этого вы можете задуматься о миграции (автоматической или ручной, с возможностью потери данных или без нее и т. Д.).
Кроме того, использование только что созданного DatabaseContext должно быть простым (вы должны иметь возможность делать все, что связано с доступом к вашему классу через стандартный интерфейс DbContext)

0
bubi 13 Сен 2016 в 06:41