2016-09-06 78 views
8

Entity-Framework'ü projeme dahil etmeye çalışıyorum! Projem eklenti tabanlı olduğundan, hangi nesnenin veritabanına kaydetmem gerektiğini bilmiyorum.Varlık-Çerçeve otomatik güncelleştirmesi

yüzden bu özelliği ekledik:

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

} 

Ama bir değişiklik verince ben bu istisna olsun:

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).

Bu hata tamamen mantıklı. Veritabanının senkronizasyonu yok, ancak güncellemeyi nasıl alacağım? Bu konuda bir şey okudum:

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

Ama nasıl ve nerede doğru şekilde kullanacağımı bilmiyorum! Çok teşekkür ederim!

Edit1 i çalıştığınızda : Enable-Göçler -EnableAutomaticMigrations

bu hata var:

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

Kalıcılık katmanınız için yanlış bir araç kullanıyorsunuz gibi görünüyor. NoSQL çözümleri hakkında düşündünüz mü? –

+0

@raderick Bu bir seçenek değil .... – Flo

+0

Güncelleştirme-Veritabanı -Verbose kullanarak powershell veya nuget paket yöneticisi konsolunu güncellemeyi güncellemeyi denediniz mi? Ayrıca, göç tarafından oluşturulan yeni bir tabloyu işaret eden boş başvuru nedir? – GaelSa

cevap

5

Ne yapmak istiyorsun, ancak bazı sınırlamaları vardır.

Çözüm:

Birincisi, yapıcı gelen

Database.Initialize(true); 

kaldırın. Yapıcı, geçişler için dahil olmak üzere birden çok kez olarak adlandırılır.

İkincisi, şöyle Sonra yapıcı değiştirmek bu

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

gibi bir yapılandırma sınıfı oluşturmak:

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

ve bitirdiniz. Eklentilerdeki varlık türleri için veritabanı tabloları buna göre otomatik olarak oluşturulur/güncellenir.

Özetle, temel olarak bu, otomatik geçişler etkinleştirilmiş, ancak OnModelCreating geçersiz kılma içinden dinamik varlık türü kaydı/yapılandırması bulunan standart bir Kod İlkesi yaklaşımıdır.

Sınırlamalar:

  • Eğer AutomaticMigrationDataLossAllowed = true set yoksa mevcut eklenti kaldırıldığında bunun karşılık gelen tabloları silmek izin verilmediğinden, EF istisna oluşturur. Ve bunu yaparsanız, eklenti tabloları silinir, bu yüzden eklenti tekrar eklenirse, sıfırdan başlayacaktır.

  • Eklenti varlıkları yalnızca Veri Notları kullanılarak yapılandırılabilir. Onları tam kontrol vermek istiyorsanız, eklenti arayüzünü değiştirmeniz ve varlık türlerini almak yerine, bazı yöntemleri çağırmak ve DbModelBuilder'u geçmek yerine, varlık türlerini kendileri yapılandırmak için Fluent API'yi kullanmaları gerekir.

+0

Teşekkür ederim! Çalışıyor! Tek bir soru: Eklenti kaldırılırsa, bu ef'in tabloları silmesini istemiyorum! Bunun hakkında bir fikrin var mı? – Flo

+1

Bahsettiğim gibi bir sorun. Varlık türü kaydetmezseniz, EF silinmiş olduğunu varsayar. Yukarıda belirtilen seçeneği (varsayılan olarak 'false') ayarlamazsanız, istisna alırsınız. Ne yazık ki AFAIK mevcut tabloları terk etmenize izin veren bir seçenek yok. Yani ya hep ya hiç bir şey almazsın :( –

+0

Pekala çok teşekkür ederim! – Flo

0

Değişmesini sanmıyorum Bu yaklaşımı kullanarak hiç EF6 ile çalışın.

EF, DbSet'lerin bağlam sınıfı üzerindeyken, DatabaseContext sınıfınızı anında (eklenti varlıklarına dayanarak) oluşturup derlemeniz ve yüklemeniz gerekir. Bundan sonra geçiş hakkında düşünmeye başlayabilirsiniz (otomatik veya manuel, veri kaybına izin verip vermemek vb.). Başarısız olursa, olarak mesajları yapıştırın lütfen

Update-Database –Verbose 

:
Ayrıca yeni oluşturulan DatabaseContext basit olmalıdır kullanılarak

1

Çalıştır (her şeyi standart DbContext arayüzü aracılığıyla sınıfa erişen yapmak mümkün olmalıdır) bir yorum.