C#数据库连接教程:从基础到高级实践


一、数据库连接基础

1.1 ADO.NET架构概述

ADO.NET是.NET平台数据访问的核心组件,主要包含:

  • Connection:建立与数据库的连接
  • Command:执行SQL命令
  • DataReader:高效读取数据
  • DataAdapter:数据库与DataSet之间的桥梁
  • DataSet:内存中的数据库表示

1.2 .NET数据提供程序

数据库类型提供程序命名空间程序集
SQL ServerSystem.Data.SqlClientSystem.Data.SqlClient
OracleOracle.ManagedDataAccess.ClientOracle.ManagedDataAccess
MySQLMySql.Data.MySqlClientMySql.Data
PostgreSQLNpgsqlNpgsql
SQLiteMicrosoft.Data.SqliteMicrosoft.Data.Sqlite

二、SQL Server连接实战

2.1 基本连接步骤

using System.Data.SqlClient;

// 连接字符串示例(实际使用时应加密或从配置读取)
string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";

// 创建连接对象
using (SqlConnection connection = new SqlConnection(connectionString))
{
    try
    {
        // 打开连接
        connection.Open();
        Console.WriteLine("连接成功!");

        // 执行数据库操作...
    }
    catch (SqlException ex)
    {
        Console.WriteLine($"数据库错误: {ex.Message}");
    }
    // using块结束会自动关闭连接
}

2.2 参数化查询(防止SQL注入)

string productName = "笔记本电脑";
decimal price = 5999.99m;

using (SqlConnection connection = new SqlConnection(connectionString))
{
    string sql = "INSERT INTO Products (Name, Price) VALUES (@name, @price)";

    using (SqlCommand command = new SqlCommand(sql, connection))
    {
        // 添加参数
        command.Parameters.AddWithValue("@name", productName);
        command.Parameters.AddWithValue("@price", price);

        connection.Open();
        int rowsAffected = command.ExecuteNonQuery();
        Console.WriteLine($"插入了 {rowsAffected} 行数据");
    }
}

三、使用Entity Framework Core

3.1 ORM基础配置

// 安装NuGet包:Microsoft.EntityFrameworkCore.SqlServer
public class ApplicationDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=MyShopDB;Trusted_Connection=True;");
    }
}

// 实体类示例
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

3.2 基本CRUD操作

// 添加数据
using (var context = new ApplicationDbContext())
{
    var product = new Product { Name = "无线鼠标", Price = 129.99m };
    context.Products.Add(product);
    context.SaveChanges();
}

// 查询数据
using (var context = new ApplicationDbContext())
{
    var expensiveProducts = context.Products
                                .Where(p => p.Price > 500)
                                .OrderByDescending(p => p.Price)
                                .ToList();

    foreach (var product in expensiveProducts)
    {
        Console.WriteLine($"{product.Name} - {product.Price:C}");
    }
}

四、连接池与性能优化

4.1 连接字符串配置选项

"Server=myServer;Database=myDB;User ID=myUser;Password=myPwd;
 Max Pool Size=100;         // 最大连接数
 Min Pool Size=5;           // 最小连接数
 Connection Timeout=30;      // 连接超时(秒)
 Pooling=true;              // 启用连接池
 MultipleActiveResultSets=true"  // 启用MARS

4.2 最佳实践

  1. 及时释放连接资源
   // 正确做法 - 使用using语句
   using (SqlConnection connection = new SqlConnection(connectionString))
   {
       // 操作数据库
   }
  1. 避免频繁开关连接
   // 执行多个操作时保持连接打开
   using (var connection = new SqlConnection(connectionString))
   {
       connection.Open();

       // 操作1
       // 操作2
       // ...
   }
  1. 使用异步方法处理高并发
   public async Task<List<Product>> GetProductsAsync()
   {
       using (var connection = new SqlConnection(connectionString))
       {
           await connection.OpenAsync();

           return await connection.QueryAsync<Product>(
               "SELECT * FROM Products WHERE Price > @minPrice",
               new { minPrice = 100 });
       }
   }

五、多数据库支持

5.1 使用Dapper轻量级ORM

// 安装NuGet包:Dapper
using Dapper;

public class ProductRepository
{
    private readonly string _connectionString;

    public ProductRepository(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IEnumerable<Product> GetProducts(int categoryId)
    {
        using (var connection = new SqlConnection(_connectionString))
        {
            return connection.Query<Product>(
                "SELECT * FROM Products WHERE CategoryId = @catId",
                new { catId = categoryId });
        }
    }
}

5.2 数据库无关抽象

public interface IDatabaseConnection
{
    IEnumerable<T> Query<T>(string sql, object parameters = null);
    int Execute(string sql, object parameters = null);
}

// SQL Server实现
public class SqlServerConnection : IDatabaseConnection
{
    private readonly string _connectionString;

    public SqlServerConnection(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IEnumerable<T> Query<T>(string sql, object parameters = null)
    {
        using (var connection = new SqlConnection(_connectionString))
        {
            return connection.Query<T>(sql, parameters);
        }
    }

    // 其他方法实现...
}

六、安全注意事项

6.1 连接字符串安全

  1. 不要硬编码连接字符串
   // 正确做法:从配置读取
   var connectionString = Configuration.GetConnectionString("DefaultConnection");
  1. 使用Windows身份验证
   "Server=myServer;Database=myDB;Integrated Security=True;"
  1. 生产环境使用加密存储

6.2 SQL注入防护

  1. 始终使用参数化查询
   // 错误做法(易受SQL注入攻击)
   string sql = $"SELECT * FROM Users WHERE Name = '{userInput}'";

   // 正确做法
   string sql = "SELECT * FROM Users WHERE Name = @name";
   command.Parameters.AddWithValue("@name", userInput);
  1. 使用ORM或查询构建器

七、常见问题解决

7.1 连接超时问题

// 增加连接超时时间
"Server=myServer;Database=myDB;User ID=myUser;Password=myPwd;Connect Timeout=60;"

// 代码中设置Command超时
using (var command = new SqlCommand(sql, connection))
{
    command.CommandTimeout = 120; // 秒
    // 执行命令
}

7.2 连接泄漏检测

// 在连接字符串中添加以下参数监控连接泄漏
"Application Name=MyApp;Pooling=true;Max Pool Size=100;Connection Lifetime=30"

八、现代数据库访问模式

8.1 仓储模式实现

public interface IRepository<T> where T : class
{
    Task<T> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(T entity);
}

public class ProductRepository : IRepository<Product>
{
    private readonly ApplicationDbContext _context;

    public ProductRepository(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<Product> GetByIdAsync(int id)
    {
        return await _context.Products.FindAsync(id);
    }

    // 其他方法实现...
}

8.2 使用依赖注入

// 在Startup.cs中配置
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddScoped<IRepository<Product>, ProductRepository>();
}

// 在控制器中使用
public class ProductsController : Controller
{
    private readonly IRepository<Product> _productRepository;

    public ProductsController(IRepository<Product> productRepository)
    {
        _productRepository = productRepository;
    }

    public async Task<IActionResult> Index()
    {
        var products = await _productRepository.GetAllAsync();
        return View(products);
    }
}

结语

本教程涵盖了C#数据库连接的核心技术,从基础的ADO.NET到现代ORM框架。关键要点包括:

  1. 理解不同数据访问技术的适用场景
  • ADO.NET:精细控制、高性能需求
  • EF Core:快速开发、复杂领域模型
  • Dapper:简单查询、轻量级ORM
  1. 掌握连接管理的最佳实践
  • 正确管理连接生命周期
  • 合理配置连接池
  • 使用异步方法提高吞吐量
  1. 重视数据访问安全
  • 保护连接字符串
  • 防止SQL注入
  • 实施适当的访问控制

随着.NET生态的发展,数据库访问技术也在不断演进。建议开发者:

  1. 关注Entity Framework Core的最新功能
  2. 了解云原生数据库访问模式
  3. 学习分布式事务处理
  4. 掌握性能调优技术

通过本教程的学习,您应该能够根据项目需求选择合适的数据访问策略,构建高效、安全的数据库应用程序。


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注