797 字
4 分钟
C# 实战:动态创建 SQL Server 数据库与表

引言#

在常规开发中,我们通常手动创建数据库。但在某些场景下(如软件首次运行初始化、多租户 SaaS 系统的隔离部署),我们需要通过代码在运行时动态创建数据库和表结构。本文将展示如何利用 ADO.NET 高效、安全地完成这一操作。


1. 核心连接字符串配置#

要创建数据库,必须先连接到 SQL Server 的系统库 master

// 注意:Initial Catalog 留空或设为 master,因为此时目标数据库尚未创建
public string connString = @"Data Source=.;Initial Catalog=master;Integrated Security=SSPI;TrustServerCertificate=True;";

2. 检查数据库是否存在#

在创建之前执行检查,可以避免 SQL 报错。我们通过查询系统视图 sys.databases 来实现。

public bool IsDBExist(string dbName)
{
// 使用参数化查询防止 SQL 注入(虽然此处是数据库名,但也应养成好习惯)
string sql = "SELECT 1 FROM master.dbo.sysdatabases WHERE name = @dbName";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@dbName", dbName);
conn.Open();
object result = cmd.ExecuteScalar();
return result != null;
}
}

3. 动态创建数据库#

创建数据库的操作必须在 master 连接下执行。我们可以指定文件存储路径(MDF/LDF)以及初始大小。

public void CreateDataBase(string dbName, string dbPath)
{
if (IsDBExist(dbName)) return;
// 格式化 SQL 语句(注意:数据库名不支持参数化,需严格过滤输入内容)
string sql = $@"
CREATE DATABASE [{dbName}] ON PRIMARY
(NAME = '{dbName}', FILENAME = '{dbPath}{dbName}.mdf', SIZE = 10MB, MAXSIZE = 100MB, FILEGROWTH = 10%)
LOG ON
(NAME = '{dbName}_log', FILENAME = '{dbPath}{dbName}_log.ldf', SIZE = 5MB, MAXSIZE = 50MB, FILEGROWTH = 5MB)";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
}

4. 检查与动态创建表#

数据库创建后,我们需要切换到目标数据库执行 CREATE TABLE

4.1 检查表是否存在#

public bool IsTableExist(string dbName, string tableName)
{
string sql = $"USE [{dbName}]; SELECT 1 FROM sysobjects WHERE id = object_id('{tableName}') AND type = 'U'";
// ... 执行逻辑同 IsDBExist ...
}

4.2 动态定义字段并建表#

我们可以利用 Dictionary<string, string> 灵活定义列名和类型。

public void CreateDataTable(string dbName, string tableName, Dictionary<string, string> columns)
{
if (!IsDBExist(dbName)) throw new Exception("目标数据库不存在!");
if (IsTableExist(dbName, tableName)) return;
// 构建字段 SQL 字符串
List<string> fieldDefs = new List<string> { "ID INT IDENTITY(1,1) PRIMARY KEY" };
foreach (var column in columns)
{
fieldDefs.Add($"[{column.Key}] {column.Value}");
}
string sql = $"USE [{dbName}]; CREATE TABLE [{tableName}] ({string.Join(",", fieldDefs)})";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
}

5. 进阶建议与注意事项#

  • 权限问题:执行 CREATE DATABASE 需要账号拥有 sysadmindbcreator 角色权限。
  • 路径权限:代码指定的 dbPath 所在的文件夹,必须授予 SQL Server 服务账号(通常是 NT Service\MSSQLSERVER)读写权限。
  • 连接池管理:使用 using 块是处理 SqlConnection 的最佳实践,它能确保即使发生异常,连接也能被及时关闭。
  • SQL 注入防御:由于 DDL 语句(如 CREATE)不支持参数化对象名(表名/库名),请务必在传入参数前使用正则表达式检查输入的合法性。

总结#

通过 C# 与 ADO.NET 的配合,我们可以将数据库的管理逻辑封装进应用程序中。这不仅提升了软件的自动化程度,也减少了部署时的手动操作成本。

C# 实战:动态创建 SQL Server 数据库与表
https://sw.rscclub.website/posts/sqlserverdtcjkhb/
作者
杨月昌
发布于
2018-05-12
许可协议
CC BY-NC-SA 4.0