Khởi tạo cơ sở dữ liệu trong Entity Framework

Chúng ta đã thấy Code First tự động tạo cơ sở dữ liệu trong phần ví dụ Code First đơn giản. Nếu bạn đã bỏ lỡ bài viết thì có thể xem tại đây:

Code First trong Entity Framework | Comdy
Code First là gì? Làm sao để sử dụng cách tiếp cận Code First trong Entity Framework.

Ở bài viết này, chúng ta sẽ tìm hiểu cách Entity Framework quyết định tên cơ sở dữ liệu và máy chủ trong khi khởi tạo cơ sở dữ liệu theo cách tiếp cận Code First.

Hình dưới đây cho thấy một quy trình khởi tạo cơ sở dữ liệu, dựa trên tham số được truyền trong phương thức khởi tạo cơ sở của lớp Context được kế thừa từ lớp DbContext:

Khởi tạo cơ sở dữ liệu trong Entity Framework

Tham số khởi tạo cơ sở dữ liệu

Theo hình trên, phương thức khởi tạo cơ sở của lớp Context có thể có tham số sau:

  1. Không có tham số.
  2. Tên cơ sở dữ liệu.
  3. Tên chuỗi kết nối.

Không có tham số

Nếu bạn không chỉ định tham số trong phương thức khởi tạo cơ sở của lớp Context thì nó sẽ tạo cơ sở dữ liệu trong máy chủ SQLEXPRESS cục bộ của bạn với tên khớp với {Namespace}. {Tên lớp Context}.

Ví dụ, Entity Framework (EF) sẽ tạo một cơ sở dữ liệu có tên SchoolDataLayer.Context cho lớp Context sau:

namespace SchoolDataLayer
{
    public class Context: DbContext 
    {
        public Context(): base()
        { }
    }
}

Tên cơ sở dữ liệu

Bạn cũng có thể chỉ định tên cơ sở dữ liệu làm tham số trong phương thức khởi tạo cơ sở của lớp Context.

Nếu bạn chỉ định tham số tên cơ sở dữ liệu, thì Code First sẽ tạo cơ sở dữ liệu với tên bạn đã chỉ định trong phương thức khởi tạo cơ sở trong máy chủ cơ sở dữ liệu SQLEXPRESS cục bộ.

Ví dụ, Code First sẽ tạo cơ sở dữ liệu có tên MySchoolDB cho lớp Context sau.

namespace SchoolDataLayer
{
    public class Context: DbContext 
    {
        public Context(): base("MySchoolDB") 
        { }
    }
}

Tên chuỗi kết nối

Bạn cũng có thể chỉ định chuỗi kết nối trong app.config hoặc web.config và chỉ định tên chuỗi kết nối bắt đầu bằng "name =" trong phương thức khởi tạo cơ sở của lớp Context.

Hãy xem xét ví dụ sau nơi chúng ta truyền tham số name=SchoolDBConnectionString trong phương thức khởi tạo cơ sở.

namespace SchoolDataLayer
{
    public class Context: DbContext 
    {
        public SchoolDBContext() : base("name=SchoolDBConnectionString") 
        {
        }
    }
}

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <connectionStrings>
        <add name="SchoolDBConnectionString" 
             connectionString="Data Source=.;Initial Catalog=SchoolDB;Integrated Security=true" 
             providerName="System.Data.SqlClient"/>
    </connectionStrings>
</configuration>

Trong lớp Context ở trên, chúng tôi chỉ định tên chuỗi kết nối làm tham số. Xin lưu ý rằng tên chuỗi kết nối phải bắt đầu bằng "name =", nếu không, nó sẽ coi nó là tên cơ sở dữ liệu.

Tên cơ sở dữ liệu trong chuỗi kết nối trong App.config là SchoolDB. Entity Framework (EF) sẽ tạo cơ sở dữ liệu SchoolDB mới hoặc sử dụng cơ sở dữ liệu SchoolDB hiện có trong SQL Server cục bộ.

Đảm bảo rằng bạn có thuộc tính providerName="System.Data.SqlClient" cho cơ sở dữ liệu SQL Server trong chuỗi kết nối.

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>


Bài viết liên quan:

2 kịch bản lưu dữ liệu trong Entity Framework Core là kịch bản được kết nối và kịch bản ngắt kết nối.

Tạo ứng dụng .NET Core Console đầu tiên và cấu hình sử dụng Entity Framework Core.

Truy vấn trong Entity Framework Core có gì mới? Truy vấn trong EF Core khác EF ở những điểm nào.