Nếu là tôi (khi là tôi ...):
Bạn đặc biệt không muốn cố gắng làm cho các tệp cơ sở dữ liệu hoạt động bằng cách sao chép chúng và đính kèm chúng - có những lý do khiến bạn có thể muốn nhưng tôi tin rằng đây là những ngoại lệ chứ không phải là quy tắc.
Theo đó, những gì bạn cần làm là tạo tập lệnh cho cơ sở dữ liệu, tức là sử dụng SQL DDL để tạo cơ sở dữ liệu và các bảng cũng như tất cả những thứ khác trong lược đồ của bạn.
Khá nhiều thứ bạn cần để cho phép bạn làm điều này là các quyền thích hợp đối với phiên bản máy chủ và sau đó là một chuỗi kết nối (mà bạn có thể có thể xây dựng ngoài tên máy chủ / phiên bản).
Từ đây:
- Có cơ sở dữ liệu không? Nếu không tạo nó.
- Nếu có một cơ sở dữ liệu, nó có phải là phiên bản lược đồ phù hợp không? Nếu quá thấp, hãy cập nhật nó hoặc thông báo cho người dùng và rút lui một cách duyên dáng tùy thuộc vào cách bạn muốn mọi thứ hoạt động như thế nào. Nếu quá cao, chỉ cần lùi lại và thông báo rằng cần có phiên bản cập nhật của ứng dụng
- Tất cả vẫn như bình thường, hãy tiếp tục.
Theo quan điểm mã:phương pháp xác định xem cơ sở dữ liệu có tồn tại hay không; phương pháp tạo cơ sở dữ liệu "trống" tiêu chuẩn với bảng phiên bản và số phiên bản là 0; các phương pháp để đưa lược đồ lên phiên bản hiện tại bằng cách chạy DDL thích hợp (chúng tôi mã hóa của chúng tôi thành C # vì nó cung cấp tính linh hoạt hơn nhưng bạn cũng có thể chạy các tập lệnh DDL theo trình tự).
Nó có tồn tại không:
public virtual bool Exists()
{
bool exists = false;
string masterConnectionString = this.CreateConnectionString(this.Server, this.FailoverServer, "master");
this.DBConnection.ConnectionString = masterConnectionString;
this.DBConnection.Open();
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = this.DBConnection;
cmd.CommandText = "SELECT COUNT(name) FROM sysdatabases WHERE name = @DBName";
cmd.Parameters.AddWithValue("@DBName", this.DBName);
exists = (Convert.ToInt32(cmd.ExecuteScalar()) == 1);
}
finally
{
this.DBConnection.Close();
}
return exists;
}
Tạo cơ sở dữ liệu mới:
public virtual void CreateNew()
{
string createDDL = @"CREATE DATABASE [" + this.DBName + "]";
this.BuildMasterConnectionString();
this.DBConnection.Open();
try
{
this.ExecuteSQLStmt(createDDL, this.DefaultSQLTimeout, null);
}
finally
{
this.DBConnection.Close();
}
createDDL = @"
CREATE TABLE AAASchemaVersion
(
Version int NOT NULL,
DateCreated datetime NOT NULL,
Author nvarchar(30) NOT NULL,
Notes nvarchar(MAX) NULL
);
ALTER TABLE AAASchemaVersion ADD CONSTRAINT PK_Version PRIMARY KEY CLUSTERED
(
Version
);
INSERT INTO AAASchemaVersion
(Version, DateCreated, Author, Notes)
VALUES
(0, GETDATE(), 'James Murphy', 'Empty Database')
";
this.BuildConnectionString();
this.ConnectionString += ";pooling=false";
this.DBConnection.Open();
try
{
this.ExecuteSQLStmt(createDDL, this.DefaultSQLTimeout, null);
}
catch (Exception ex)
{
throw new Exception("Exception while creating / initialising AAASchemaVersion", ex);
}
finally
{
this.DBConnection.Close();
}
}
Mã cập nhật phức tạp hơn một chút nhưng về cơ bản chạy những thứ như sau:
CREATE TABLE AuditUser
(
ID int IDENTITY(1,1) NOT NULL,
UserSourceTypeID tinyint NOT NULL,
DateCreated smalldatetime NOT NULL,
UserName nvarchar(100) NOT NULL
);
ALTER TABLE AuditUser
ADD CONSTRAINT
PK_AuditUser PRIMARY KEY CLUSTERED
(
ID
),
CONSTRAINT [FK_AuditUser_UserSourceType] FOREIGN KEY
(
UserSourceTypeID
) REFERENCES UserSourceType (
ID
);
Tất cả được gói gọn trong một giao dịch cho mỗi lần cập nhật - vì vậy nếu cập nhật không thành công, bạn nên để cơ sở dữ liệu ở trạng thái tốt đã biết.
Tại sao lại làm theo cách này (trong mã, không phải là không có thử nghiệm của nó?) Và kết quả cuối cùng là mức độ tin cậy cao rằng lược đồ mà ứng dụng của bạn đang nói chuyện là lược đồ mà ứng dụng của bạn muốn nói chuyện với ... các bảng phù hợp, cột bên phải (theo đúng thứ tự, đúng loại và độ dài phù hợp), v.v., v.v. và điều này sẽ tiếp tục như vậy theo thời gian.
Xin lỗi nếu điều này hơi dài - nhưng đây là điều tôi khá quan tâm ...