Si fuera yo (cuando soy yo...):
En particular, no desea intentar hacer que los archivos de la base de datos funcionen copiándolos y adjuntándolos; hay razones por las que podría querer hacerlo, pero creo que se trata de excepciones en lugar de reglas.
En consecuencia, lo que debe hacer es crear un script para la creación de la base de datos, es decir, usar SQL DDL para crear la base de datos y las tablas y todo lo demás en su esquema.
Casi todo lo que necesita para permitirle hacer esto son los derechos apropiados para la instancia del servidor y luego una cadena de conexión (que probablemente pueda construir aparte del nombre del servidor/instancia).
Desde aquí:
- ¿Existe una base de datos? Si no, créalo.
- Si hay una base de datos, ¿es la versión correcta del esquema? Si es demasiado bajo, actualícelo o avise al usuario y retroceda con gracia dependiendo de cómo quiera que funcionen las cosas. Si es demasiado alto, retroceda y aconseje que se requiere una versión actualizada de la aplicación
- Todo es como debe ser, continúa.
Desde el punto de vista del código:método para determinar si existe una base de datos; método para crear una base de datos estándar "vacía" con una tabla de versiones y un número de versión de 0; métodos para actualizar el esquema a la versión actual ejecutando el DDL apropiado (codificamos el nuestro en C# porque brinda más flexibilidad, pero igualmente podría ejecutar secuencias de comandos DDL en secuencia).
¿Existe?:
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;
}
Crear una nueva base de datos:
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();
}
}
El código de actualización es un poco más complejo, pero básicamente ejecuta cosas como esta:
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
);
Todo envuelto en una transacción por actualización, de modo que si la actualización falla, debe abandonar la base de datos en un buen estado conocido.
¿Por qué hacerlo de esta manera (en código, que no está exento de pruebas?) Bueno, el resultado final es un alto grado de confianza de que el esquema con el que está hablando su aplicación es el esquema con el que su aplicación espera hablar... tablas correctas, columnas correctas (en el orden correcto, que sean del tipo correcto y la longitud correcta), etc, etc. y que esto seguirá siendo así con el tiempo.
Disculpas si esto es un poco largo, pero esto es algo en lo que estoy muy interesado...