7天掌握ADO.NET:从“小白”到“大神”的数据库访问秘籍!

🔥关注墨瑾轩,带你探索编程的奥秘!🚀
🔥超萌技术攻略,轻松晋级编程高手🚀
🔥技术宝库已备好,就等你来挖掘🚀
🔥订阅墨瑾轩,智趣学习不孤单🚀
🔥即刻启航,编程之旅更有趣🚀

在这里插入图片描述在这里插入图片描述

当ADO.NET遇上“数据库江湖”

“各位看官,今天咱们不聊武侠小说,来说说现代程序员的“数据库江湖”——ADO.NET!想象你的代码像“跑酷达人”,却因为不会用ADO.NET而卡在数据库门口?那可真是‘拿着算盘玩量子计算机’——太Low啦!”


从“小白”到“大神”的修炼手册

一、ADO.NET基础:连接数据库的“武林秘籍”

1. 核心组件初探
// 创建SQL Server连接(C#示例)
using System;
using System.Data.SqlClient;

public class DatabaseConnection {
    public void ConnectToDatabase() {
        string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"; // 连接字符串
        using (SqlConnection connection = new SqlConnection(connectionString)) { // 使用using自动释放资源
            try {
                connection.Open(); // 打开连接
                Console.WriteLine("数据库连接成功!");
            } catch (SqlException ex) {
                Console.WriteLine("连接失败:" + ex.Message); // 异常处理
            }
        }
    }
}

代码注释解析

  • SqlConnection是连接数据库的“钥匙”,connectionString是“密码本”。
  • using语句确保资源自动释放,避免内存泄漏。
  • try-catch是程序员的“护甲”,防止程序崩溃。
2. 小故事:某程序员第一次用ADO.NET时,把Password写成了PassWord,结果数据库死活连不上…(教训:细节决定成败!)

二、数据操作:从“只读”到“增删改”的“七十二变”

1. 查询数据(DataReader篇)
// 使用SqlDataReader读取数据
public void ReadData() {
    string query = "SELECT * FROM Users";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlCommand command = new SqlCommand(query, connection); // 创建命令
        try {
            connection.Open();
            SqlDataReader reader = command.ExecuteReader(); // 执行查询
            while (reader.Read()) { // 逐行读取
                Console.WriteLine($"ID: {reader["ID"]}, Name: {reader["Name"]}"); // 输出数据
            }
        } catch (SqlException ex) {
            Console.WriteLine("读取失败:" + ex.Message);
        }
    }
}

专业建议

  • SqlDataReader是“只读游标”,适合快速读取大量数据。
  • reader.Read()是“向前走”的逻辑,不能回头哦!
2. 插入数据(Command篇)
// 插入新用户
public void InsertUser(string name, int age) {
    string query = "INSERT INTO Users (Name, Age) VALUES (@Name, @Age)"; // 参数化查询
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlCommand command = new SqlCommand(query, connection);
        command.Parameters.AddWithValue("@Name", name); // 绑定参数
        command.Parameters.AddWithValue("@Age", age);
        try {
            connection.Open();
            int rowsAffected = command.ExecuteNonQuery(); // 执行插入
            Console.WriteLine($"{rowsAffected} 行已插入。");
        } catch (SqlException ex) {
            Console.WriteLine("插入失败:" + ex.Message);
        }
    }
}

代码注释解析

  • @Name@Age是参数占位符,防止SQL注入。
  • ExecuteNonQuery()用于增删改操作,返回受影响行数。
3. 小故事:某程序员忘记用参数化查询,直接拼接SQL,结果被黑客“黑”了数据库…(教训:永远别信用户输入!)

三、DataAdapter与DataSet:离线操作的“乾坤大挪移”

1. 数据适配器(DataAdapter篇)
// 使用DataAdapter填充DataSet
public void LoadDataWithDataAdapter() {
    string query = "SELECT * FROM Products";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlDataAdapter adapter = new SqlDataAdapter(query, connection); // 创建适配器
        DataSet dataSet = new DataSet(); // 离线数据集
        try {
            adapter.Fill(dataSet, "Products"); // 填充数据
            DataTable productsTable = dataSet.Tables["Products"];
            foreach (DataRow row in productsTable.Rows) {
                Console.WriteLine($"ProductID: {row["ProductID"]}, Name: {row["ProductName"]}"); // 输出数据
            }
        } catch (SqlException ex) {
            Console.WriteLine("加载失败:" + ex.Message);
        }
    }
}

代码注释解析

  • DataAdapter是“桥梁”,负责在数据库和DataSet之间传递数据。
  • DataSet是“离线数据库”,适合复杂操作(如排序、筛选)。
2. 更新数据(DataAdapter篇)
// 更新数据并提交回数据库
public void UpdateDataWithDataAdapter() {
    string query = "SELECT * FROM Products";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
        SqlCommandBuilder builder = new SqlCommandBuilder(adapter); // 自动生成更新命令
        DataSet dataSet = new DataSet();
        adapter.Fill(dataSet, "Products");

        DataTable productsTable = dataSet.Tables["Products"];
        // 修改第一行数据
        if (productsTable.Rows.Count > 0) {
            DataRow row = productsTable.Rows[0];
            row["Price"] = 99.99; // 修改价格
            row.SetModified(); // 标记为已修改
        }

        try {
            adapter.Update(dataSet, "Products"); // 提交更改
            Console.WriteLine("数据已更新。");
        } catch (SqlException ex) {
            Console.WriteLine("更新失败:" + ex.Message);
        }
    }
}

专业建议

  • SqlCommandBuilder是“自动翻译官”,根据DataAdapter生成UPDATE命令。
  • SetModified()是关键,否则DataAdapter不会提交更改。

四、事务处理:从“单打独斗”到“团队协作”

1. 事务管理(Transaction篇)
// 事务处理示例
public void PerformTransaction() {
    string query1 = "UPDATE Accounts SET Balance = Balance - 100 WHERE AccountID = 1";
    string query2 = "UPDATE Accounts SET Balance = Balance + 100 WHERE AccountID = 2";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        connection.Open();
        SqlTransaction transaction = connection.BeginTransaction(); // 开始事务
        try {
            SqlCommand command = connection.CreateCommand();
            command.Transaction = transaction; // 关联事务

            command.CommandText = query1;
            command.ExecuteNonQuery(); // 执行第一条SQL

            command.CommandText = query2;
            command.ExecuteNonQuery(); // 执行第二条SQL

            transaction.Commit(); // 提交事务
            Console.WriteLine("转账成功!");
        } catch (SqlException ex) {
            transaction.Rollback(); // 回滚事务
            Console.WriteLine("转账失败:" + ex.Message);
        }
    }
}

代码注释解析

  • SqlTransaction是“原子操作”,要么全成功,要么全失败。
  • Commit()是“确认”,Rollback()是“撤销”。
2. 小故事:某程序员忘记提交事务,结果用户的钱一直“卡在半路”…(教训:事务必须显式提交!)

五、性能优化:从“卡顿地狱”到“丝滑天堂”

1. 异步操作(Async/Await篇)
// 异步查询数据
public async Task ReadDataAsync() {
    string query = "SELECT * FROM Logs";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlCommand command = new SqlCommand(query, connection);
        try {
            await connection.OpenAsync(); // 异步打开连接
            SqlDataReader reader = await command.ExecuteReaderAsync(); // 异步执行查询
            while (await reader.ReadAsync()) { // 异步读取
                Console.WriteLine($"LogID: {reader["LogID"]}, Message: {reader["Message"]}");
            }
        } catch (SqlException ex) {
            Console.WriteLine("异步读取失败:" + ex.Message);
        }
    }
}

专业建议

  • async/await是“非阻塞魔法”,让程序更流畅。
  • OpenAsync()ExecuteReaderAsync()是异步操作的“标配”。
2. 连接池配置(Connection Pooling篇)
// 优化连接池配置
string optimizedConnectionString = "Server=myServerAddress;Database=myDataBase;" +
                                   "User Id=myUsername;Password=myPassword;" +
                                   "Pooling=true;Min Pool Size=5;Max Pool Size=100;"; // 配置连接池

代码注释解析

  • Pooling=true启用连接池,减少频繁创建连接的开销。
  • Min Pool SizeMax Pool Size控制连接池的“最小兵”和“最大兵”。

六、高级技巧:从“普通玩家”到“隐藏大佬”

1. 参数化查询进阶
// 动态构建参数化查询
public void SearchUsers(string nameFilter, int minAge) {
    string query = "SELECT * FROM Users WHERE 1=1"; // 1=1是占位符
    List<SqlParameter> parameters = new List<SqlParameter>();

    if (!string.IsNullOrEmpty(nameFilter)) {
        query += " AND Name LIKE @Name"; // 动态添加条件
        parameters.Add(new SqlParameter("@Name", $"%{nameFilter}%"));
    }

    if (minAge > 0) {
        query += " AND Age >= @MinAge";
        parameters.Add(new SqlParameter("@MinAge", minAge));
    }

    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlCommand command = new SqlCommand(query, connection);
        command.Parameters.AddRange(parameters.ToArray()); // 添加参数
        try {
            connection.Open();
            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read()) {
                Console.WriteLine($"ID: {reader["ID"]}, Name: {reader["Name"]}, Age: {reader["Age"]}");
            }
        } catch (SqlException ex) {
            Console.WriteLine("搜索失败:" + ex.Message);
        }
    }
}

小技巧1=1是SQL中的“万能开关”,方便动态拼接条件。

2. LINQ to ADO.NET(简化查询)
// 使用LINQ查询DataSet
public void QueryWithLinq() {
    string query = "SELECT * FROM Products";
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        SqlDataAdapter adapter = new SqlDataAdapter(query, connection);
        DataSet dataSet = new DataSet();
        adapter.Fill(dataSet, "Products");

        var expensiveProducts = from row in dataSet.Tables["Products"].AsEnumerable()
                                where row.Field<decimal>("Price") > 100
                                select row;

        foreach (var product in expensiveProducts) {
            Console.WriteLine($"Expensive Product: {product["ProductName"]}, Price: {product["Price"]}");
        }
    }
}

专业建议:LINQ是“SQL的C#版”,让代码更简洁优雅。


七、异常处理:从“手忙脚乱”到“泰山压顶不弯腰”

1. 多层异常捕获
// 多层异常处理示例
public void SafeDatabaseOperation() {
    try {
        // 数据库操作
    } catch (SqlException ex) {
        if (ex.Number == 2627) { // 主键冲突
            Console.WriteLine("主键冲突,请检查输入数据。");
        } else if (ex.Number == 547) { // 外键约束
            Console.WriteLine("外键约束错误,关联数据不存在。");
        } else {
            Console.WriteLine("数据库错误:" + ex.Message);
        }
    } catch (Exception ex) {
        Console.WriteLine("通用错误:" + ex.Message);
    } finally {
        // 清理资源
    }
}

小故事:某程序员用catch (Exception)抓了一堆异常,结果发现是网络问题…(教训:具体异常优先!)


结论:从“菜鸟”到“大神”的蜕变

最后分享个趣事:某程序员第一次用DataAdapter时,把Fill方法写成了Full,结果数据一直没加载…(教训:拼写要仔细!)

互动提问:你在使用ADO.NET时遇到过哪些“按下葫芦浮起瓢”的趣事?欢迎在评论区分享你的江湖故事!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨瑾轩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值