20

İlk Entity Framework konsepti kullanarak yeni bir veritabanı oluşturmaya çalışıyorum. Ancak kodu çalıştırırken, kod düzgün çalışmıyor olsa da (DropCreateDatabaseIfModelChanges ayarını kullanarak) veritabanı oluşturulmaz. Veritabanından bir şey almaya çalıştığımda aşağıdaki özel durumu görüyorum.Entity Framework 5 code-first veri tabanı oluşturmuyor

enter image description here

Benim projem, bir jenerik servis ve depo inşaatı ile ayrı DataAccess katmanı kullanılarak kurulduğundan. Böylece bütün varlıklarım, depolarım ve ayrıca veritabanı bağlamları çözüm içinde ayrı bir projede.

Benim global.asax dosya aşağıdaki kod parçasını içerir.

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>()); 

Bu, yoksa yeni bir veritabanını başlatmalı, doğru mu?

Veritabanı bağlam sınıfım şunun gibi görünüyor;

namespace Website.DAL.Model 
{ 
    public class MyContext : DbContext 
    { 
     public IDbSet<Project> Projects { get; set; } 
     public IDbSet<Portfolio> Portfolios { get; set; } 

     /// <summary> 
     /// The constructor, we provide the connectionstring to be used to it's base class. 
     /// </summary> 
     public MyContext() 
      : base("MyConnectionString") 
     { 
     } 

     static MyContext() 
     { 
      try 
      { 
       Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>()); 
      } 
      catch (Exception) 
      { 
       throw; 
      } 
     } 

     /// <summary> 
     /// This method prevents the plurarization of table names 
     /// </summary> 
     /// <param name="modelBuilder"></param> 
     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 
      modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); 
     } 
    } 
} 

Bu sınıfa, internetteki çeşitli eğitici ve makaleleri takip ederek oluşturdum. Her şey benim için yeni, ama görebildiğim kadarıyla her şey doğru görünüyor. Yani şimdi kullanıyorum iki varlık. 'Proje' ve 'Portföy' olarak adlandırılıyorlar. Bu gibi görünüyorlar;

public class Portfolio 
    { 
     [Key] 
     public Guid Id { get; set; } 
     public String Name { get; set; } 
     public DateTime StartDate { get; set; } 
     public DateTime? EndDate { get; set; } 
     public bool IsPublished { get; set; } 

     public virtual ICollection<Project> Projects { get; set; } 
    } 

Ve

public class Project 
    { 
     [Key] 
     public Guid Id { get; set; } 
     public DateTime StartDate { get; set; } 
     public DateTime? EndDate { get; set; } 
     public bool IsPublished { get; set; } 
     public String Title { get; set; } 
    } 

Ben harici bir sunucuda çalışan kullanıyorum veritabanı

, ben kullanıyorum barındırma sağlayıcı ile geldi. Bir SQL Server veritabanım var ve çalışıyor ve veritabanına bağlantı dizesi web sitesi projesinin web.config. Veritabanını kaldırmayı denedim ve kodun yeniden oluşturmasına izin verdim, maalesef çalışmadı. Burada bariz bir şey eksik miyim? Ya da sunucu için veritabanı oluşturma erişim hakları gibi basit bir şey olabilir mi?

Not: SQL kodu oluşturmak için Database-Update -Script komutunu çalıştırdığımda, tüm tabloları oluşturmak için doğru SQL deyimlerinin oluşturulduğu anlaşılıyor.

UPDATE 1: Pekala, bazı yorumlar sayesinde biraz daha ileri gittim. Bazı değişiklikleri zorlamak için varlıklarıma iki özellik ekledim ve bunun gibi özel bir başlatıcı da oluşturdum;

public class ForceDeleteInitializer : IDatabaseInitializer<MyContext> 
    { 
     private readonly IDatabaseInitializer<MyContext> _initializer = new DropCreateDatabaseIfModelChanges<MyContext>(); 

     public ForceDeleteInitializer() 
     { 
      //_initializer = new ForceDeleteInitializer(); 
     } 

     public void InitializeDatabase(MyContext context) 
     { 
      //This command is added to prevent open connections. See http://stackoverflow.com/questions/5288996/database-in-use-error-with-entity-framework-4-code-first 
      context.Database.ExecuteSqlCommand("ALTER DATABASE borloOntwikkel SET SINGLE_USER WITH ROLLBACK IMMEDIATE"); 
      _initializer.InitializeDatabase(context); 
     } 
    } 

Ben de bağlamın kurucusundan başlatıcı kaldırdık, bu nedenle bu ortalama i kod satırını kaldırmak ettik;

Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>()); 

Bundan sonra, bu üç satırı Global'ime ekledim.asax dosyası;

Database.SetInitializer(new ForceDeleteInitializer()); 
MyContext c = new MyContext(); 
c.Database.Initialize(true); 

Hata ayıklaması yaparken şimdi bu özel durumu alıyorum; enter image description here

Bu şu bilgileri veriyor:

  • InnerException diyor ki: sağlayıcı InnerException bir ProviderManifestToken
  • InnerException dönmedi diyor ki: "Bu işlem için bir bağlantı için asıl bağlantı açıldı ve başvurular bağlantıdan kaldırılmış olduğundan, bağlantı 'master' veritabanına genişliğinde bir bağlantı olamaz.

    muhtemelen bu konuda ne yapılabilir .. veritabanı, bu yüzden büyük olasılıkla silinmiş erişilemez bu eylemin ardından olmayan bir açık bağlantı"

veriniz? Büyük olasılıkla ana veritabanına erişemem çünkü hosting sunucum bana uygun erişim hakkını vermiyor. Ayrıntılı soru için

+0

Kod ve yapılandırma tamam görünüyor, muhtemelen barındırma durumuna takıldınız. EF, Db'nizi özel bir yardımcı tabloyla oluşturmak ister (1 veya 2 sağlama). Belki bunu yerel bir Db'den betimleyebilir ve barındırılan Db'ye taşıyabilirsiniz? –

+0

Kodunuzu çalıştıran kullanıcı hesabı, veritabanlarını bırakmak ve oluşturmak için gerekli izinlere sahip mi? – jlew

+0

@Henk, sadece oluşturulan SQL komut dosyasını çalıştırmayı denedim. Bir kayıt için benim için bir __MigrationHistory tablosu oluşturdu. Ayrıca 'this.Database.Initialize (true)' satırını ekleyerek içeriğimin yapıcısını değiştirdim. Bu bana bir hata vermedi, ancak herhangi bir tablo oluşturmadı. Daha sonra kayıtları MigrationHistory tablosundan düşürdüm ve yine aynı hatayı aldım. Bu yüzden şimdi yerel bir veritabanında çalıştırmayı ve ne olacağını görmeyi deneyeceğim. – Rob

cevap

12

: bağlantı dizesi doğru veritabanına işaret ve yetkilendirmeyi eklemek edilir

Kontrol veritabanına erişmek için böyle bağlıyor.

Veritabanını kendim yarattım ve doğru SQL kullanıcısının yapılandırıldığından ve erişimimin olduğundan emin oldum.

Sonra başlatıcıyı ve kodu Global.asax dosyasından kaldırdım. Bundan sonra Paket Yöneticisi Konsolu'nda aşağıdaki komutu çalıştırdım (katmanlı tasarımdan beri konsolda doğru projeyi seçmem gerekti); göçler sonrasında

Enable-Migrations 

etkin ve ben bir yeni göç darağacına aşağıdaki komutu koştu benim kuruluşlara bazı son dakika değişiklikleri yapılmış;

Add-Migration AddSortOrder 

benim göçler oluşturulan sonra konsolda aşağıdaki komutu koştum ve işte, veritabanı benim varlıklarla güncellendi;

Update-Database -Verbose 

i göçler sağlayan oluşturulan benim Configuraton.cs sınıfında, Tohum yöntemini geçersiz kıldık göç çalıştırırken veritabanı tohuma edebilmek. Bu yöntemdeki son kod şöyle:

protected override void Seed(MyContext context) 
     { 
      // This method will be called after migrating to the latest version. 

      //Add menu items and pages 
      if (!context.Menu.Any() && !context.Page.Any()) 
      { 
       context.Menu.AddOrUpdate(new Menu() 
              { 
               Id = Guid.NewGuid(), 
               Name = "MainMenu", 
               Description = "Some menu", 
               IsDeleted = false, 
               IsPublished = true, 
               PublishStart = DateTime.Now, 
               LastModified = DateTime.Now, 
               PublishEnd = null, 
               MenuItems = new List<MenuItem>() 
                   { 
                    new MenuItem() 
                     { 
                      Id = Guid.NewGuid(), 
                      IsDeleted = false, 
                      IsPublished = true, 
                      PublishStart = DateTime.Now, 
                      LastModified = DateTime.Now, 
                      PublishEnd = null, 
                      Name = "Some menuitem", 
                      Page = new Page() 
                         { 
                          Id = Guid.NewGuid(), 
                          ActionName = "Some Action", 
                          ControllerName = "SomeController", 
                          IsPublished = true, 
                          IsDeleted = false, 
                          PublishStart = DateTime.Now, 
                          LastModified = DateTime.Now, 
                          PublishEnd = null, 
                          Title = "Some Page" 
                         } 
                     }, 
                    new MenuItem() 
                     { 
                      Id = Guid.NewGuid(), 
                      IsDeleted = false, 
                      IsPublished = true, 
                      PublishStart = DateTime.Now, 
                      LastModified = DateTime.Now, 
                      PublishEnd = null, 
                      Name = "Some MenuItem", 
                      Page = new Page() 
                         { 
                          Id = Guid.NewGuid(), 
                          ActionName = "Some Action", 
                          ControllerName = "SomeController", 
                          IsPublished = true, 
                          IsDeleted = false, 
                          PublishStart = DateTime.Now, 
                          LastModified = DateTime.Now, 
                          PublishEnd = null, 
                          Title = "Some Page" 
                         } 
                     } 
                   } 
              }); 
      } 

      if (!context.ComponentType.Any()) 
      { 
       context.ComponentType.AddOrUpdate(new ComponentType() 
       { 
        Id = Guid.NewGuid(), 
        IsDeleted = false, 
        IsPublished = true, 
        LastModified = DateTime.Now, 
        Name = "MyComponent", 
        PublishEnd = null, 
        PublishStart = DateTime.Now 
       }); 
      } 


      try 
      { 
       // Your code... 
       // Could also be before try if you know the exception occurs in SaveChanges 

       context.SaveChanges(); 
      } 
      catch (DbEntityValidationException e) 
      { 
       //foreach (var eve in e.EntityValidationErrors) 
       //{ 
       // Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", 
       //  eve.Entry.Entity.GetType().Name, eve.Entry.State); 
       // foreach (var ve in eve.ValidationErrors) 
       // { 
       //  Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"", 
       //   ve.PropertyName, ve.ErrorMessage); 
       // } 
       //} 
       //throw; 

       var outputLines = new List<string>(); 
       foreach (var eve in e.EntityValidationErrors) 
       { 
        outputLines.Add(string.Format(
         "{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", 
         DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State)); 
        foreach (var ve in eve.ValidationErrors) 
        { 
         outputLines.Add(string.Format(
          "- Property: \"{0}\", Error: \"{1}\"", 
          ve.PropertyName, ve.ErrorMessage)); 
        } 
       } 
       System.IO.File.AppendAllLines(@"c:\temp\errors.txt", outputLines); 
       throw; 
      } 
     } 

an dezavantajı elle paket yöneticisi konsolunda (sadece) 2 komutları ile göç etmek zorunda olmasıdır. Fakat aynı zamanda, bunun dinamik bir şekilde gerçekleşmemesi de iyi bir şeydir çünkü bu, veritabanımda muhtemelen olası değişiklikleri önler. Dahası her şey sadece mükemmel çalışır.

1

+1. Benim yaklaşım değiştirmeye karar ile başka hiçbir çözüm geldiğinden beri

<add name="PatientContext" providerName="System.Data.SqlClient" connectionString="Server=SQLSERVER2; Database=Patients; uid=PatientUser; password=123456; Integrated Security=False;" /> 
0

başlatılamadığı befor sizin veritabanı oluşturmak için kod aşağıdaki çalıştırın:

context.Database.CreateIfNotExists();