当前位置:首页 > 行业动态 > 正文

如何在C中正确编写数据库插入语句?

在C#中使用ADO.NET的SqlConnection和SqlCommand对象执行数据库插入操作,需编写参数化SQL语句(如INSERT INTO)防止注入攻击,通过Parameters添加值后调用ExecuteNonQuery方法提交到数据库。

基础方法:使用ADO.NET的SqlCommand

通过SqlCommand直接操作数据库是C#最传统的交互方式,适合需要精细控制SQL的场景。

using System.Data.SqlClient;
// 示例代码
string connectionString = "Server=myServer;Database=myDB;User Id=myUser;Password=myPass;";
string insertQuery = "INSERT INTO Users (Name, Email, CreatedAt) VALUES (@Name, @Email, @CreatedAt)";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand(insertQuery, connection))
    {
        command.Parameters.AddWithValue("@Name", "John Doe");
        command.Parameters.AddWithValue("@Email", "john@example.com");
        command.Parameters.AddWithValue("@CreatedAt", DateTime.Now);
        int rowsAffected = command.ExecuteNonQuery();
        Console.WriteLine($"插入了 {rowsAffected} 行数据");
    }
}

关键点:

  • 使用using语句管理连接和命令对象,确保资源释放。
  • 参数化查询@Name等占位符)避免SQL注入攻击。
  • ExecuteNonQuery()返回受影响的行数,用于验证操作结果。

进阶实践:封装通用插入方法

为提升代码复用性,可封装一个通用插入函数:

public static int InsertData(string tableName, Dictionary<string, object> columns)
{
    string connectionString = "YourConnectionString";
    var columnNames = string.Join(", ", columns.Keys);
    var parameterNames = string.Join(", ", columns.Keys.Select(k => "@" + k));
    string query = $"INSERT INTO {tableName} ({columnNames}) VALUES ({parameterNames})";
    using (SqlConnection conn = new SqlConnection(connectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand(query, conn))
        {
            foreach (var pair in columns)
            {
                cmd.Parameters.AddWithValue("@" + pair.Key, pair.Value);
            }
            return cmd.ExecuteNonQuery();
        }
    }
}
// 调用示例
var data = new Dictionary<string, object>
{
    { "Name", "Alice" },
    { "Age", 30 },
    { "RegistrationDate", DateTime.Now }
};
int result = InsertData("Customers", data);

优势:

  • 动态生成SQL语句,适应不同表结构。
  • 减少重复代码量,提升开发效率。

现代方案:使用Entity Framework Core

对于大型项目,推荐通过ORM框架(如EF Core)操作数据库,降低SQL耦合度。

  1. 定义数据模型

    public class User
    {
     public int Id { get; set; }
     public string Name { get; set; }
     public string Email { get; set; }
     public DateTime CreatedAt { get; set; }
    }
  2. 插入数据

    using (var context = new MyDbContext())
    {
     var newUser = new User
     {
         Name = "Emma",
         Email = "emma@example.com",
         CreatedAt = DateTime.Now
     };
     context.Users.Add(newUser);
     int changes = context.SaveChanges();
     Console.WriteLine($"已保存 {changes} 条变更");
    }

EF Core特性:

  • 自动生成SQL语句,无需手动编写。
  • 支持事务管理、并发控制等高级功能。
  • 提供LINQ语法,增强代码可读性。

安全与性能优化

防御SQL注入

  • 禁止使用字符串拼接:
    // 高风险示例(绝对避免!)
    string unsafeQuery = $"INSERT INTO Users (Name) VALUES ('{userInput}')";
  • 必须使用参数化查询或ORM框架。

批量插入优化

当需插入大量数据时,原生ADO.NET的SqlBulkCopy性能更优:

DataTable dataTable = new DataTable();
// 构建DataTable数据...
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
    bulkCopy.DestinationTableName = "Users";
    bulkCopy.WriteToServer(dataTable);
}

异步操作

使用异步方法避免阻塞主线程:

await command.ExecuteNonQueryAsync();
await context.SaveChangesAsync();

常见问题解答

Q1:插入后如何获取自增ID?

  • ADO.NET:在SQL语句末尾添加SELECT SCOPE_IDENTITY(),通过ExecuteScalar()获取。
  • EF Core:实体对象的ID属性会自动填充。

Q2:插入时间字段时出现格式错误?

  • 始终使用参数化查询传递DateTime类型,而非字符串格式化。

Q3:如何处理特殊字符(如单引号)?

  • 参数化查询会自动转义,无需手动处理。

引用说明

  • ADO.NET官方文档:Microsoft SQL Server Data Access
  • EF Core教程:Entity Framework Core Getting Started
0