EF Code-First - Chiến lược khởi DB

Chiến lược khởi tạo cơ sở dữ liệu

Bạn đã tạo cơ sở dữ liệu sau khi chạy ứng dụng Code First lần đầu tiên, nhưng lần thứ hai trở đi thì sao? Nó sẽ tạo ra một cơ sở dữ liệu mới mỗi khi bạn chạy ứng dụng?

Còn môi trường Production thì sao? Làm thế nào để bạn cập nhật cơ sở dữ liệu khi bạn thay đổi mô hình miền của bạn?

Để xử lý các kịch bản này, bạn phải sử dụng một trong các chiến lược khởi tạo cơ sở dữ liệu.

Có bốn chiến lược khởi tạo cơ sở dữ liệu khác nhau trong Code First:

  1. CreateDatabaseIfNotExists: Đây là trình khởi tạo mặc định. Như tên gọi, nó sẽ tạo cơ sở dữ liệu nếu không tồn tại theo cấu hình. Tuy nhiên, nếu bạn thay đổi lớp mô hình và sau đó chạy ứng dụng với trình khởi tạo này, thì nó sẽ đưa ra một ngoại lệ.
  2. DropCreateDatabaseIfModelChanges: Trình khởi tạo này xóa cơ sở dữ liệu hiện có và tạo cơ sở dữ liệu mới, nếu các lớp mô hình của bạn (các lớp thực thể) đã bị thay đổi. Vì vậy, bạn không phải lo lắng về việc duy trì lược đồ cơ sở dữ liệu của mình, khi các lớp mô hình của bạn thay đổi.
  3. DropCreateDatabaseAlways: Như tên cho thấy, trình khởi tạo này sẽ xóa cơ sở dữ liệu hiện có mỗi khi bạn chạy ứng dụng, bất kể các lớp mô hình của bạn có thay đổi hay không. Điều này sẽ hữu ích khi bạn muốn có một cơ sở dữ liệu mới mỗi khi bạn chạy ứng dụng, ví dụ như khi bạn đang phát triển ứng dụng.
  4. Trình khởi tạo cơ sở dữ liệu tùy chỉnh: Bạn cũng có thể tạo trình khởi tạo tùy chỉnh của riêng mình, nếu các cách trên không đáp ứng yêu cầu của bạn hoặc bạn muốn thực hiện một số quy trình khác để khởi tạo cơ sở dữ liệu bằng trình khởi tạo ở trên.

Để sử dụng một trong các chiến lược khởi tạo cơ sở dữ liệu ở trên, bạn phải thiết lập trình khởi tạo cơ sở dữ liệu bằng cách sử dụng lớp Database trong một lớp Context, như được trình bày ở ví dụ bên dưới:

public class SchoolDBContext: DbContext 
{
    public SchoolDBContext(): base("SchoolDBConnectionString") 
    {
        Database.SetInitializer<SchoolDBContext>(new CreateDatabaseIfNotExists<SchoolDBContext>());

        //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseIfModelChanges<SchoolDBContext>());
        //Database.SetInitializer<SchoolDBContext>(new DropCreateDatabaseAlways<SchoolDBContext>());
        //Database.SetInitializer<SchoolDBContext>(new SchoolDBInitializer());
    }

    public DbSet<Student> Students { get; set; }
    public DbSet<Standard> Standards { get; set; }
}

Bạn cũng có thể tạo trình khởi tạo cơ sở dữ liệu tùy chỉnh của mình, bằng cách kế thừa một trong các trình khởi tạo, như ví dụ bên dưới:

public class SchoolDBInitializer : CreateDatabaseIfNotExists<SchoolDBContext>
{
    protected override void Seed(SchoolDBContext context)
    {
        base.Seed(context);
    }
}

Trong ví dụ trên, lớp SchoolDBInitializer là một lớp khởi tạo tùy chỉnh kế thừa từ lớp CreateDatabaseIfNotExists. Điều này giúp tách mã khởi tạo cơ sở dữ liệu ra khỏi lớp Context.

Thiết lập trình khởi tạo cơ sở dữ liệu trong file cấu hình

Bạn cũng có thể thiết lập trình khởi tạo cơ sở dữ liệu trong file cấu hình. Ví dụ minh họa thiết lập trình khởi tạo mặc định trong app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer" 
             value="System.Data.Entity.DropCreateDatabaseAlways`1[[SchoolDataLayer.SchoolDBContext, SchoolDataLayer]], EntityFramework" />
    </appSettings>
</configuration>

Bạn có thể thiết lập trình khởi tạo cơ sở dữ liệu tùy chỉnh trong file cấu hình như sau:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>    
        <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer"
             value="SchoolDataLayer.SchoolDBInitializer, SchoolDataLayer" />
    </appSettings>
</configuration>

Tắt trình khởi tạo cơ sở dữ liệu

Bạn có thể tắt trình khởi tạo cơ sở dữ liệu cho ứng dụng của mình. Giả sử rằng bạn không muốn mất dữ liệu hiện có trong môi trường Production, thì bạn có thể tắt trình khởi tạo, như được trình bày bên dưới:

public class SchoolDBContext: DbContext 
{
    public SchoolDBContext() : base("SchoolDBConnectionString")
    {            
        //Disable initializer
        Database.SetInitializer<SchoolDBContext>(null);
    }
    public DbSet<Student> Students { get; set; }
    public DbSet<Standard> Standards { get; set; }
}

Bạn cũng có thể tắt trình khởi tạo trong file cấu hình như sau:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>    
        <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer"
             value="Disabled" />
    </appSettings>
</configuration>