Ако бях аз (когато съм аз...):
Не искате особено да се опитвате да накарате файловете на базата данни да работят, като ги копирате и прикачвате - има причини, поради които може да искате, но аз вярвам, че това са по-скоро изключения, отколкото правила.
Съответно това, което трябва да направите, е да създадете скрипт за създаване на базата данни, т.е. да използвате SQL DDL, за да създадете базата данни и таблиците и всички останали неща във вашата схема.
Почти всичко, от което се нуждаете, за да можете да направите това, са подходящи права за екземпляра на сървъра и след това низ за връзка (който вероятно можете да създадете отделно от името на сървъра/екземпляра).
От тук:
- Има ли база данни? Ако не го създайте.
- Ако има база данни, правилната версия на схемата ли е? Ако е твърде ниско, или го актуализирайте, или посъветвайте потребителя и се върнете елегантно в зависимост от това как искате нещата да работят. Ако е твърде високо, просто се върнете и уведомете, че е необходима актуализирана версия на приложението
- Всичко е както трябва, продължавайте.
От гледна точка на код:метод за определяне дали база данни съществува; метод за създаване на стандартна "празна" база данни с таблица с версии и номер на версия 0; методи за привеждане на схемата до текущата версия чрез стартиране на подходящия DDL (ние кодираме нашия в C#, защото осигурява повече гъвкавост, но можете също така да изпълнявате DDL скриптове последователно).
Съществува ли:
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;
}
Създайте нова база данни:
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();
}
}
Кодът за актуализация е малко по-сложен, но в общи линии изпълнява неща като това:
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
);
Всичко е обвито в транзакция за актуализация - така че ако актуализацията е неуспешна, трябва да оставите базата данни в известно добро състояние.
Защо го правите по този начин (в код, който не е без изпитания?) добре, крайният резултат е висока степен на увереност, че схемата, с която вашето приложение говори, е схемата, с която приложението ви очаква да говори... правилни таблици, десни колони (в правилния ред, които са правилния тип и правилната дължина) и т.н. и т.н. и че това ще продължи да е така във времето.
Извинявам се, ако това е малко дълго - но това е нещо, което много ме интересува...