Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie erstellt man eine eingebettete SQL 2008-Datenbankdatei, wenn sie nicht existiert?

Wenn ich es wäre (wenn ich es wäre...):

Sie möchten nicht unbedingt versuchen, Datenbankdateien zum Laufen zu bringen, indem Sie sie kopieren und anhängen - es gibt Gründe, warum Sie dies tun möchten, aber ich glaube, dies sind eher Ausnahmen als Regeln.

Dementsprechend müssen Sie die Datenbank per Skript erstellen, d. h. SQL DDL verwenden, um die Datenbank und die Tabellen und all die anderen Dinge in Ihrem Schema zu erstellen.

So ziemlich alles, was Sie dazu benötigen, sind entsprechende Rechte für die Serverinstanz und dann eine Verbindungszeichenfolge (die Sie wahrscheinlich neben dem Server-/Instanznamen erstellen können).

Von hier:

  1. Gibt es eine Datenbank? Wenn nicht, erstellen Sie es.
  2. Wenn es eine Datenbank gibt, ist es die richtige Schemaversion? Wenn es zu niedrig ist, aktualisieren Sie es entweder oder informieren Sie den Benutzer und kehren Sie elegant zurück, je nachdem, wie die Dinge funktionieren sollen. Wenn es zu hoch ist, ziehen Sie sich einfach zurück und weisen Sie darauf hin, dass eine aktualisierte Version der Anwendung erforderlich ist
  3. Alles ist wie es sein sollte, weitermachen.

Aus Code-Sicht:Methode, um festzustellen, ob eine Datenbank existiert; Methode zum Erstellen einer standardmäßigen "leeren" Datenbank mit einer Versionstabelle und einer Versionsnummer von 0; Methoden, um das Schema auf die aktuelle Version zu bringen, indem die entsprechende DDL ausgeführt wird (wir codieren unsere in C#, weil sie mehr Flexibilität bietet, aber Sie könnten auch DDL-Skripts nacheinander ausführen).

Existiert es:

    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;
    }

Erstellen Sie eine neue Datenbank:

    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();
        }
    }

Der Aktualisierungscode ist etwas komplexer, läuft aber im Grunde so ab:

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
    );

Alles verpackt in einer Transaktion pro Update - so dass Sie, wenn das Update fehlschlägt, die Datenbank in einem bekannten guten Zustand belassen sollten.

Warum machen Sie das so (im Code, der nicht ohne Tests ist?) Nun, das Endergebnis ist ein hohes Maß an Vertrauen, dass das Schema, mit dem Ihre App kommuniziert, das Schema ist, mit dem Ihre App kommunizieren soll ... richtige Tabellen, richtige Spalten (in der richtigen Reihenfolge, das sind der richtige Typ und die richtige Länge), etc, etc. und dass dies auch im Laufe der Zeit so bleiben wird.

Entschuldigung, wenn das ein bisschen lang ist - aber das ist etwas, worauf ich sehr scharf bin ...