2016-09-06 3 views
8

내 프로젝트에 Entity-Framework를 구현하려고합니다! 내 프로젝트는 플러그인 기반이므로 어떤 객체를 데이터베이스에 저장해야하는지 알지 못합니다.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); 
    } 

} 

하지만 변화를 줄 때 나는,이 예외를 얻을 :

The model backing the 'DatabaseContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

이 오류는 completly 논리적이다. 데이터베이스가 동기화되지 않았지만 업데이트를 어떻게받을 수 있습니까? 나는 이것에 관하여 무언가를 읽었다 :

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

그러나 나는 그것을 어떻게 그리고 정확하게 사용해야하는지 모른다! 대단히 감사합니다!

EDIT1 : 내가하려고하면 가 : 사용-마이그레이션 -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> 
+0

지속성 레이어에 잘못된 도구가 사용 된 것 같습니다. noSQL 솔루션에 대해 생각하십니까? –

+0

@raderick 이것은 옵션이 아닙니다 .... – Flo

+0

Update-Database -Verbose를 사용하여 powershell 또는 nuget 패키지 관리자 콘솔을 업데이트하려고 시도 했습니까? 또한 마이그레이션에서 생성 된 새 테이블을 가리키는 null 참조입니까? – GaelSa

답변

5

당신이 할 수있는 일은 있지만 몇 가지 제한이 있습니다.

솔루션 :

첫째, 생성자에서

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>()); 
} 

하면 모든 작업이 완료된다. 플러그인의 엔티티 유형에 대한 데이터베이스 테이블은 그에 따라 자동으로 생성/업데이트됩니다.

기본적으로 이것은 자동 마이그레이션이 활성화되었지만 OnModelCreating 재정의 내부에서 동적 엔터티 유형 등록/구성을 사용하는 표준 코드 우선 접근 방식입니다.

제한 :

  • 당신이 AutomaticMigrationDataLossAllowed = true를 설정하지 않으면 기존의 플러그인이 제거 될 때이 해당 테이블을 삭제할 수 있지 않기 때문에, EF는 예외를 생성합니다. 그렇게하면 플러그인 테이블이 삭제되므로 플러그인을 다시 추가하면 0부터 시작됩니다.

  • 플러그인 엔티티는 데이터 어노테이션 만 사용하여 구성 할 수 있습니다. 플러그인을 완벽하게 제어하려면 플러그인 인터페이스를 변경하고 엔티티 유형을 가져 오는 대신 일부 메소드를 호출하고 DbModelBuilder을 전달해야하므로 Fluent API를 사용하여 엔티티 유형 자체를 구성 할 수 있습니다.

+0

감사합니다 !!! 그것은 일하고있다! 단 하나의 질문 : 나는 플러그인이 제거되면 그 ef가 테이블을 삭제하는 것을 원하지 않는다! 이거 좀 생각해? – Flo

+1

내가 언급 한대로 그게 문제입니다. 엔티티 유형을 등록하지 않으면 EF는 엔티티 유형이 삭제되었다고 간주합니다. 앞서 언급 한 옵션을 설정하지 않으면 (기본적으로'false') 예외가 발생합니다. 불행히도 AFAIK 기존 테이블을 남겨 둘 수있는 옵션이 없습니다. 그래서 당신은 모두 또는 아무것도 얻지 않습니다 : ( –

+0

대단히 감사합니다! – Flo

0

내가 그것을 것 생각하지 않습니다 이 접근 방식을 사용하여 EF6에서 작업 할 수 있습니다.

EF는 DbSets가 컨텍스트 클래스에 있어야하므로 DatabaseContext 클래스를 즉석에서 생성 (플러그 인 엔티티 기반)해야 컴파일하고로드 할 수 있습니다. 그런 다음 마이그레이션에 대해 생각할 수 있습니다 (자동 또는 수동, 데이터 유실 여부 등의 유무에 관계없이). 실패하면, 같은 메시지를 붙여주십시오

Update-Database –Verbose 

:
또한 방금 만든 DatabaseContext이 간단해야 사용

1

실행 (당신은 모든 표준 DbContext 인터페이스를 통해 클래스에 접근 할 수 있어야한다) 의견.

관련 문제