20

Tôi đang cố tạo một cơ sở dữ liệu mới bằng cách sử dụng khái niệm đầu tiên của khung Entity Framework. Tuy nhiên khi chạy mã cơ sở dữ liệu không được tạo ra (sử dụng thiết lập DropCreateDatabaseIfModelChanges), mặc dù mã đang chạy tốt. Tôi thấy ngoại lệ sau khi tôi cố gắng lấy thứ gì đó từ cơ sở dữ liệu.Entity Framework 5 code-first không tạo cơ sở dữ liệu

enter image description here

Dự án của tôi được thiết lập sử dụng một lớp riêng biệt DataAccess với một dịch vụ chung và xây dựng kho. Vì vậy, tất cả các thực thể của tôi, kho lưu trữ và bối cảnh cơ sở dữ liệu cũng nằm trong một dự án riêng biệt trong giải pháp.

Tệp global.asax của tôi chứa đoạn mã sau.

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

Điều này sẽ khởi tạo cơ sở dữ liệu mới nếu không có ở đó, phải không?

Lớp ngữ cảnh cơ sở dữ liệu của tôi trông như thế này;

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

Tôi đã tạo lớp này theo một số hướng dẫn và bài viết trên internet. Đó là tất cả mới với tôi, nhưng theo như tôi có thể thấy tất cả mọi thứ có vẻ chính xác cho đến nay. Vì vậy, bây giờ hai thực thể tôi đang sử dụng. Chúng được gọi là 'Project' và 'Portfolio'. Họ trông như thế này;

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

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

Cơ sở dữ liệu Tôi đang sử dụng đang chạy trên một máy chủ bên ngoài, nó đi kèm với các nhà cung cấp hosting Tôi đang sử dụng. Tôi đã có một cơ sở dữ liệu SQL Server và chạy và chuỗi kết nối đến cơ sở dữ liệu nằm trong web.config của dự án trang web. Tôi đã thử loại bỏ cơ sở dữ liệu và để cho mã tái tạo nó, mà tiếc là không hoạt động. Tôi có thiếu thứ gì đó hiển nhiên ở đây không? Hoặc nó có thể là một điều đơn giản như quyền truy cập vào máy chủ để tạo cơ sở dữ liệu?

Lưu ý: Khi tôi chạy lệnh Database-Update -Script để tạo mã SQL, có vẻ như các câu lệnh SQL đúng để tạo tất cả các bảng được tạo.

CẬP NHẬT 1: Được rồi, nhờ một số nhận xét tôi đã tiến xa hơn một chút. Tôi đã thêm hai thuộc tính cho các thực thể của mình để bắt buộc một số thay đổi và tôi cũng đã tạo một trình khởi tạo tùy chỉnh như thế này;

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

Tôi cũng đã xóa trình khởi tạo khỏi hàm tạo của ngữ cảnh, vì vậy điều này có nghĩa là tôi đã xóa dòng mã này;

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

Sau đó tôi đã thêm ba dòng này vào toàn cầu của mình.tập tin asax;

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

Khi gỡ lỗi, tôi hiện đang nhận ngoại lệ này; enter image description here

này mang lại cho tôi những thông tin sau:

  • InnerException cho biết: Các nhà cung cấp không trở về một ProviderManifestToken
  • InnerException trong InnerException cho biết: "Đối với hoạt động này một kết nối đến Kết nối không thể là đã tạo chiều rộng cơ sở dữ liệu 'master' vì kết nối ban đầu là được mở và các tham chiếu đã bị xóa khỏi kết nối. Vui lòng cung cấp một kết nối không mở"

Sau những hành động cơ sở dữ liệu là không thể tiếp cận, vì vậy rất có thể xóa ..

gì có thể có thể được thực hiện về vấn đề này? Nó rất có thể là tôi không thể truy cập cơ sở dữ liệu tổng thể vì hostingprovider của tôi sẽ không cho tôi quyền truy cập thích hợp.

+0

Mã và cấu hình trông OK, có thể bạn đang gặp phải tình huống lưu trữ. EF muốn tạo Db của bạn với một bảng trợ giúp đặc biệt trong đó (1 hoặc 2 băm). Có lẽ bạn có thể kịch bản nó từ một Db địa phương và di chuyển nó vào Db lưu trữ? –

+0

Tài khoản người dùng đang chạy mã của bạn có các quyền cần thiết để thả và tạo cơ sở dữ liệu không? – jlew

+0

@Henk, tôi vừa thử chạy tập lệnh SQL đã tạo. Nó tạo ra một bảng __MigrationHistory cho tôi với một bản ghi. Tôi cũng đã sửa đổi hàm tạo của ngữ cảnh của tôi bằng cách thêm dòng 'this.Database.Initialize (true)'. Điều này đã không cho tôi một lỗi, nhưng không tạo ra bất kỳ bảng nào. Sau đó tôi đã xóa bản ghi từ bảng MigrationHistory và tôi lại gặp lỗi tương tự. Vì vậy, tôi sẽ thử chạy nó trên một cơ sở dữ liệu địa phương ngay bây giờ và xem những gì sẽ xảy ra. – Rob

Trả lời

12

Vì không có giải pháp khác đi ngang qua tôi quyết định thay đổi cách tiếp cận của tôi.

Tôi đã tự tạo cơ sở dữ liệu lần đầu tiên và đảm bảo rằng người dùng SQL chính xác được định cấu hình và tôi có quyền truy cập.

Sau đó, tôi đã xóa trình khởi tạo và mã từ tệp Global.asax. Sau đó tôi chạy lệnh sau trong Package Manager Console (kể từ khi thiết kế lớp tôi đã phải chọn dự án chính xác trong giao diện điều khiển);

Enable-Migrations 

Sau khi di chuyển nơi đã bật và tôi thực hiện một số thay đổi vào phút cuối đối với thực thể của mình, tôi chạy lệnh dưới đây để tạo một di chuyển mới;

Add-Migration AddSortOrder 

Sau khi di chuyển của tôi được tạo, tôi đã chạy lệnh sau trong bảng điều khiển và thì cơ sở dữ liệu đã được cập nhật với thực thể của tôi;

Update-Database -Verbose 

Để có thể tạo cơ sở dữ liệu khi chạy di chuyển, tôi đã ghi đè phương thức Seed trong lớp Configuraton.cs, được tạo khi bật di chuyển. Mã cuối cùng trong phương thức này là như thế này;

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

Bất lợi tại thời điểm này là tôi phải di chuyển thủ công bằng (chỉ) 2 lệnh trong bảng điều khiển trình quản lý gói. Nhưng đồng thời, thực tế là điều này không xảy ra tự động cũng tốt bởi vì điều này ngăn chặn những thay đổi có thể có trong cơ sở dữ liệu của tôi. Hơn nữa mọi thứ hoạt động hoàn hảo.

1

+1 cho câu hỏi chi tiết.

Kiểm tra xem chuỗi kết nối của bạn chỉ vào cơ sở dữ liệu chính xác và thêm sự cho phép thuộc tính như thế này để truy cập vào cơ sở dữ liệu của bạn:

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

befor intialize nó chạy sau mã để tạo cơ sở dữ liệu của bạn:

context.Database.CreateIfNotExists();

Các vấn đề liên quan