【IT168技术】1. ADO.NET 3.0 用于访问和操作数据的两个主要组件是: .NET Framework 数据提供程序 (虚线框内) 和 DataSet。
.NET Framework 数据提供程序是专门为数据操作以及快速、只进、只读访问数据而设计的组件。
ADO.NET DataSet 是专门为独立于任何数据源的数据访问而设计的。


注意:新手面试经常会遇到考这样的题:ADO.NET 的五大对象,就是 上面四种 + DataSet 要牢牢记住哦。后期开发也经常用到。
2. Connection 对象(只介绍SqlConnection和JDBC)
使用connection连接的时候记得打开、关闭(返回连接池),建议使用using,这样就不会忘记关了,将自动断开连接,即使发生无法处理的异常。
string connectionString = "数据库连接字符串";
using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); .... } ODBC 比较麻烦 请参考微软技术文档:http://support.microsoft.com/kb/310988 (我很少用到)
using (OdbcConnection connection = new OdbcConnection(connectionString)) { connection.Open(); .... }
3.Command对象

下面用一个实例讲解Connection 和 Command、DataReader以及储存过程和参数的设置:

(1.)下载安装微软提供的Northwind数据库:
/Files/Simcoder/微软提供的数据库.rar 含帮助文档 简单容易操作 数据库安装后 文件默认在C盘 然后附加即可
(2.)找到提供的存储过程:(本实例 使用倒数第二个 SalesByCategory 存储过程做演示)
(3.)简单查看一下存储过程的代码,其实通过名字都能知道大概做什么用
---------------------- *创*建*存*储*过*程* ----------------------- set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go ALTER PROCEDURE [dbo].[SalesByCategory] --修改存储过程[SalesByCategory] @CategoryName nvarchar(15), @OrdYear nvarchar(4) = '1998' --设置参数 (以下的实现暂不用管) AS IF @OrdYear != '1996' AND @OrdYear != '1997' AND @OrdYear != '1998' BEGIN SELECT @OrdYear = '1998' END SELECT ProductName, TotalPurchase=ROUND(SUM(CONVERT(decimal(14,2), OD.Quantity * (1-OD.Discount) * OD.UnitPrice)), 0) FROM [Order Details] OD, Orders O, Products P, Categories C WHERE OD.OrderID = O.OrderID AND OD.ProductID = P.ProductID AND P.CategoryID = C.CategoryID AND C.CategoryName = @CategoryName AND SUBSTRING(CONVERT(nvarchar(22), O.OrderDate, 111), 1, 4) = @OrdYear GROUP BY ProductName ORDER BY ProductName ---------------------- *执*行*存*储*过*程* ----------------------- USE [Northwind] GO DECLARE @return_value int EXEC @return_value = [dbo].[SalesByCategory] @CategoryName = N'Produce', @OrdYear = N'1998' SELECT 'Return Value' = @return_value GO --需要设置@CategoryName,@OrdYear(可以不设置 为空上面有判断)参数值查询
结果是:

4.)新建一个控制台的应用程序 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.SqlClient; using System.Data; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { GetSalesByCategory("server=.;uid=sa;pwd=123456;database=Northwind", "Produce");//在这里就默认设置了 参数@CategoryName参数的值为 Produce } static void GetSalesByCategory(string connectionString,string categoryName) { using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand command = new SqlCommand(); command.Connection = connection; command.CommandText = "SalesByCategory"; //CommandType 属性设置为 StoredProcedure 时,CommandText 属性应设置为存储过程的名称 command.CommandType = CommandType.StoredProcedure; //设置执行类型为存储过程 SqlParameter parameter = new SqlParameter(); parameter.ParameterName = "@CategoryName";//指定存储过程中的那个参数 parameter.SqlDbType = SqlDbType.NVarChar;//指定数据类型 parameter.Direction = ParameterDirection.Input;//指定参数为输入 parameter.Value = categoryName; command.Parameters.Add(parameter); connection.Open(); SqlDataReader reader = command.ExecuteReader(); if (reader.HasRows)//判断是否有数据行 { while (reader.Read()) { Console.WriteLine("{0}: {1:C}", reader[0], reader[1]); } } else { Console.WriteLine("No rows found."); } reader.Close();//记得关闭 Console.ReadLine(); } } } }
前面简单提到了 Connection 、DataReader、Comand以及参数和存储过程的用法,现在更加深入的学习。
1.DataReader的用法:
DataReader 从数据库中检索只读、只进的数据流。查询结果在查询执行时返回,在并存储在客户端的网络缓冲区中,直到您使用 DataReader 的 Read 方法对它们发出请求。 使用 DataReader 可以提高应用程序的性能,原因是它只要数据可用就立即检索数据,并且(默认情况下)一次只在内存中存储一行,减少了系统开销。
例子见上一篇即可,说说使用DataReader的心得,在做项目中,有时候一个实体类中的字段又是另外一个实体雷,存在外键的关系。如下实体类源码 中就有2个这样的关系(高亮代码):
using System; using System.Collections.Generic; using System.Text; namespace BookShop.Model { [Serializable] public class Book { /// /// 图书编号 /// private int id; public int Id { get { return id; } set { id = value; } } /// /// 图书标题 /// private string title; public string Title { get { return title; } set { title = value; } } /// /// 图书作者 /// private string author; public string Author { get { return author; } set { author = value; } } /// /// 图书出版社 /// private Publisher publisher; public Publisher Publisher { get { return publisher; } set { publisher = value; } } /// /// 图书出版日期 /// private DateTime publishDate; public DateTime PublishDate { get { return publishDate; } set { publishDate = value; } } /// /// 图书ISBN编号 /// private string isbn; public string Isbn { get { return isbn; } set { isbn = value; } } /// /// 图书总字数 /// private int wordsCount; public int WordsCount { get { return wordsCount; } set { wordsCount = value; } } /// /// 图书价格 /// private decimal unitPrice; public decimal UnitPrice { get { return unitPrice; } set { unitPrice = value; } } /// /// 图书描述 /// private string contentDescription; public string ContentDescription { get { return contentDescription; } set { contentDescription = value; } } /// /// 图书作者描述 /// private string authorDescription; public string AuthorDescription { get { return authorDescription; } set { authorDescription = value; } } /// /// 图书作者评语 /// private string editorComment; public string EditorComment { get { return editorComment; } set { editorComment = value; } } /// /// 图书目录 /// private string toc; public string Toc { get { return toc; } set { toc = value; } } /// /// 图书的分类 /// private Category category; public Category Category { get { return category; } set { category = value; } } /// /// 图书点击 /// private int clicks; public int Clicks { get { return clicks; } set { clicks = value; } } } }
如果是这种关系,使用Datareader 就可能会出现异常,因为当代码读到 外键的时候,外键也要使用connection连接 这时就会抛出异常,所以
与数据进行动态交互,例如绑定到 Windows 窗体控件或组合并关联来自多个源的数据。
对数据执行大量的处理,而不需要与数据源保持打开的连接,从而将该连接释放给其他客户端使用。就使用DataSet或DataTable比较合适。
也许你不太明白,但是你可以这样简单的记住,当实体类或数据库设计存在主外键关系的时候,使用Datareader就要谨慎了! 不过也没关系,很多经验都是从Debug学到的。
就好像微软的视频一样,为爱Debug。