0

我使用 C#、ADO.Net 和在 Server Management Studio 中创建的嵌入式 MS SQL 2008 数据库文件(附加到 MS SQL 2008 Express)创建了一个数据库应用程序。有人可以向我指出一个资源,该资源描述了如果数据库文件丢失(比如在我的应用程序安装后),我如何以编程方式创建数据库文件?

4

2 回答 2

2

如果是我(当它是我时......):

您并不特别希望通过复制和附加它们来尝试使数据库文件正常工作 - 您可能想要这样做是有原因的,但我认为这些是例外而不是规则。

因此,您需要做的是编写数据库创建脚本,即使用 SQL DDL 创建数据库和表以及架构中的所有其他内容。

使您能够执行此操作所需的几乎就是对服务器实例的适当权限,然后是一个连接字符串(您可能可以在服务器/实例名称之外构建它)。

从这里:

  1. 有数据库吗?如果不创建它。
  2. 如果有数据库,它是正确的模式版本吗?如果太低,请更新它或建议用户并根据您希望事情的工作方式优雅地退出。如果太高,请退出并建议需要更新版本的应用程序
  3. 一切都是应有的,继续。

从代码上看:判断数据库是否存在的方法;使用版本表和版本号 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
    );

每次更新都包含在一个事务中 - 因此,如果更新失败,您应该让数据库处于已知的良好状态。

为什么要这样做(在代码中,它并非没有经过试验?)最终结果是高度确信您的应用程序正在与之交谈的架构是您的应用程序期望与之交谈的架构......正确的表,正确的列(以正确的顺序,即正确的类型和正确的长度)等,等等,并且随着时间的推移,这种情况将继续存在。

抱歉,如果这有点长 - 但这是我非常热衷的事情......

于 2009-11-11T15:40:24.780 回答
0

如果“嵌入式 MS SQL”是“Microsoft SQL Server Compact 3.5”:

using (SqlCeEngine sqlCeEngine = new SqlCeEngine(connectionString))
  sqlCeEngine.CreateDatabase();
于 2009-11-11T15:02:45.190 回答