2015-11-30 21 views
14

Veritabanımız için Kod İlk Entity Framework'ü kullandığımız bir projedeyim.Programlı kod ilk geçişleri oluşturma

Oluşturulan bir MSI paketini tüketmek için sürekli entegrasyonumuzun tamamını değiştirmek istiyoruz ancak EF birkaç komplikasyon sunuyor.

web'den çeşitli şeyler denedi, ama en AutomaticMigrationstrue yanı sıra AutomaticMigrationDataLossAllowed ayarlı gerektirir görünmektedir (bkz: http://romiller.com/2012/02/09/running-scripting-migrations-from-code/).

.NET yansıtıcısına bakarak Add-Migration'un ne yaptığını çoğaltmaya çalıştım ancak Powershell aracılığıyla çağrılan System.Data.Entity.Migrations.AddMigrationCommand komutunu çağırmanın bir yolunu bulamıyorum.

Son derece dağınık bir şey yapmadan bunu başarmaya nasıl yaklaşabileceğim konusunda hiç kimse hiç bir fikre sahip değil mi? Bir çok insanın yapmak istediği/yapacağı bir şey var ...

Çok teşekkürler şimdiden!

+0

Bu aracın gerçekten taşıma dosyaları oluşturup bunları projeye eklemesini ister misiniz? Veya veritabanını mevcut kod şemanızla mı güncelleyin? Eğer ikincisiyse, otomatik geçişler neden bir seçenek değil? Eğer eskiyse, 'Add-Migration' komutunu çalıştıran bir derleme etkinliği ekleyemez misiniz? – Rob

+0

@Rob CI'mızın bunu tüketebileceği ve bizim için bir taşıma arkamızdaki bizim geçişlerimizi yaratabileceğimiz bir araç yaratmaya çalışıyoruz. Bu, bir MSI'yi otomatik olarak bu işlemden oluşturmamızı sağlar, böylece model geçişler ile senkronize kalır ve MSI kırılmaz. Veritabanımızın ölçeğinden dolayı, otomatik geçişler neredeyse kesinlikle otomatik veri kaybına yol açacaktır. "Add-Migration", VS kabuğunun dışından erişilebilir gibi görünmüyor. – LukeHennerley

+0

"Otomatik geçişler neredeyse otomatik veri kaybına yol açacaktır" konusuna açıklık getirebilir misiniz? Neden * * komut dosyanızla çalışan Add-Migration ve EF Add-Migration çalışanı arasında bir fark olduğunu düşünüyorsunuz? Yoksa bu sadece manuel geçişleri çalıştırmak ve otomatik/manuel karıştırmadan kaçınmak mı istiyorsunuz? –

cevap

8

Her şeyden önce, görsel stüdyo dışında Nuget powershell'i çalıştırmanın bir yolu yok (DTE kullanıyor). Ayrıca, Visual Studio olmadan yazdığınız her şeyin csproj'a manuel olarak yerleştirilmesi gerekir (ancak zor bir görev değil).

Sadece nasıl çalıştığını göstermek için size bir kod satırı gönderiyorum. Onları sınamak için , MyDll dll (bağlam ve varlıklar ile bir proje sınaması) oluşturun ve sonra Mümkün Olur geçişler ile MyDll (yalnızca Configuration.cs oluşturmak için) el ile geçişleri etkinleştirin. Eğer ben ad unuttum

DbConnectionInfo connectionStringInfo = new DbConnectionInfo(
    "Server=.;Database=MigrationTest;User=sa;Password=dacambiare", "System.Data.SqlClient"); // We shoud retrieve this from App.config 

ToolingFacade toolingFacade = new ToolingFacade(
    "MyDll", // MigrationAssemblyName. In this case dll should be located in "C:\\Temp\\MigrationTest" dir 
    "MyDll", // ContextAssemblyName. Same as above 
    null, 
    "C:\\Temp\\MigrationTest", // Where the dlls are located 
    "C:\\Temp\\MigrationTest\\App.config", // Insert the right directory and change with Web.config if required 
    "C:\\Temp\\App_Data", 
    connectionStringInfo) 
{ 
    LogInfoDelegate = s => {Console.WriteLine(s);}, 
    LogWarningDelegate = s => { Console.WriteLine("WARNING: " + s); }, 
    LogVerboseDelegate = s => { Console.WriteLine("VERBOSE: " + s); } 
}; 


ScaffoldedMigration scaffoldedMigration = toolingFacade.Scaffold("MyMigName", "C#", "MyAppNameSpace", false); 

Console.WriteLine(scaffoldedMigration.DesignerCode); 
Console.WriteLine("=================="); 
Console.WriteLine(scaffoldedMigration.UserCode); 

// Don't forget the resource file that is in the scaffoldedMigration 

kaynak kodu düzenleme
oluşturmak için kod parçasını kullanabilir ve böylece burada sık kullanılmayan Bundan sonra

sen

using System; 
using System.Data.Entity.Infrastructure; 
using System.Data.Entity.Migrations.Design; 
4

Sorunuza gerçek bir cevap değil, deneyimimden çok payımı: Bu şekilde sizin için oluşturulan geçişlere çok dikkat ediyorum. Göçler oluşturduğumda (VS) çoğu kez bunları gözden geçiriyorum. Önerilen değişikliklerin benim olmasını istediğim şey olup olmadığını ve EF'in aptalca bir şey yapmaya çalışmadığını kontrol ediyorum (tabloyu bırakarak ve yeni bir tane oluşturarak sütun/tablo yeniden adlandırmak gibi).

Ayrıca bazen bazı kritik değişiklikler eksik EF - kısa süre önce nvarchar alanlarının uzunluklarını değiştirdiğimde doğru geçişleri oluşturma konusunda sıkıntılar yaşadım. Bu ayrıca, göçlerin dikkatli bir şekilde gözden geçirilmesini de gerektirdi.

Ve geçişleriniz de koddur. Üretime gidebilmeleri için göçmenlerin akran değerlendirmeleri yapıyoruz. Göçler otomatik olarak oluşturulursa, bu değişiklikler daha az görünür hale gelir ve potansiyel olarak üretimde veri kaybına neden olabilir.

Ayrıca, ekip ortamında geçişlerle uğraşıyorsanız - bunu iletişim yoluyla çözdük: bir geliştiricinin yeni bir geçişi kontrol ettiği her defasında - bu projedeki diğer tüm devrelere e-postalar gönderilir. Bütün sorunlarımızı çözdük.

Güncelleştirme Sadece bir meslektaşı ile bir tartışma yaptım ve başka bir sorun çıktı - yerel gelişimini nasıl yaparsınız? Dev'in makinesinde geçişler oluşturursunuz, her şeyin işe yarayıp yaramadığından emin olun. Daha sonra taşıma işlemini silin ve kodu kontrol edin. ve sonra CI'niz göçünüzü yeniden oluşturacak mı? EF ile çalışırken bu, devlerin aklını başaracaktır.

+0

Yup - göçmenlerin geliştiricilerinden kontrol edilmesini önlemek zorunda kalacaksınız veya sorunlara neden olacak – GraemeMiller

+1

@trailmax Geliştiricilerimiz (şu anda) otomatik geçişlerle çalıştıkça, geliştirme ortamındaki değişiklikleri modifiye ettiğimizde veritabanını bırakıp yeniden oluşturuyoruz. Kod tabanlı geçişler ile çalışırken, bir ekip içinde ve kaynak kontrolünde meydana gelen sorunları önler. Ancak, benim düşünmediğim bazı ilginç noktalar yaratıyorsunuz, EF ve kod tabanlı geçişleri kullanarak canlı yayınının başlangıcındayız ve zamanımızı tekrar edersek muhtemelen EF rotasını düşürmeyecektik. . Faiz dışı takımınızdaki kod tabanlı geçişleri nasıl ele alıyorsunuz? – LukeHennerley

+0

@LukeHennerley Otomatik geçişler bizim için hiç işe yaramadı - çok fazla voodoo. Ekibimiz kod ilk modelinde değişiklikler yapar, 'add-migrasyon' komutunu verir, göç iskelesini alır - doğru bir göç olup olmadığını iki kez kontrol eder. Yerel dev veritabanına uygular, her şeyin beklendiği gibi çalıştığından emin olur. İskele göçünün ilk defa doğru olduğu nadirdir. Daha sonra DB'yi yeniden scaffolden entegrasyon testlerini sıfırdan yürütür. Ve her şey yolunda olduğunda, bu kontrol edilmeye başlıyor, yeni göç hakkında ekibi e-postalayan geliştirici tarafından takip ediliyor. – trailmax

1

programlı şöyle geçişleri oluşturmak için System.Data.Entity.Migrations.Design.MigrationScaffolder sınıfını kullanabilirsiniz: Ben bizim yapı sunucuda bu ve diğer teknikler kullanarak

[TestMethod] 
public void GenerateTestMigration() 
{ 
    var config = new MyDbMigrationsConfiguration(); 
    var scaffolder = new MigrationScaffolder(config); 
    var pendingMigration = scaffolder.Scaffold("TestMigration"); 
    Trace.WriteLine(pendingMigration.UserCode); 
} 

bekleyen göçler varsa veya bir göç olması gerekiyorsa yapı başarısız böyle oluşturuldu:

using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Data.Entity.Migrations; 
using System.Data.Entity.Migrations.Design; 
using System.Diagnostics; 
using System.Linq; 

namespace YabbaDabbaDoo 
{ 
    [TestClass] 
    public class MigrationTests 
    { 
     [TestMethod] 
     [TestCategory("RunOnBuild")] 
     public void VerifyThereAreNoPendingMigrations() 
     { 
      // Arrange 
      var config = new MyDbMigrationsConfiguration(); 
      var dbMigrator = new DbMigrator(config); 

      // Act 
      var pendingMigrations = dbMigrator.GetPendingMigrations().ToList(); 

      // Visual Assertion 
      Trace.WriteLine(pendingMigrations); 

      // Assert 
      Assert.AreEqual(0, pendingMigrations.Count(), "There are pending EF migrations that need to be ran."); 
     } 

     [TestMethod] 
     [TestCategory("RunOnBuild")] 
     public void VerifyDatabaseIsCompatibleWithModel() 
     { 
      // Arrange 
      var context = new MyDbContext(); 

      // Act 
      var isCompatible = context.Database.CompatibleWithModel(false); 

      // Visual Assertion 
      if (!isCompatible) 
      { 
       var config = new MyDbMigrationsConfiguration(); 
       var scaffolder = new MigrationScaffolder(config); 
       var pendingMigration = scaffolder.Scaffold("MissingMigration"); 

       Trace.WriteLine("Missing Migration:"); 
       Trace.WriteLine(""); 
       Trace.WriteLine(pendingMigration.UserCode); 
      } 

      // Assert 
      Assert.IsTrue(isCompatible, "The EF model is not compatible with the database. An EF migration needs to be created. See output for sample of missing migration."); 
     } 
    } 
}