您的位置:首页 > 职场人生

黑马程序员——ADO.Net学习笔记

2012-04-08 09:45 495 查看
---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------

ADO.Net基础

简介:
1.程序要和数据库交互要通过ADO.Net进行,通过ADO.Net就能在程序中执行SQL了。ADO.Net中提供了对各种不同数据库的统一操作接口。

2.直接在项目中内嵌mdf文件的方式使用SQLServer数据库(基于服务的数据库)。mdf文件随着项目走,用起来方便,和在数据库服务器上创建数据库没什么区别,运行的时候会自动附加(Attach)。

3.双击mdf文件会在“服务器资源管理器”中打开,管理方式和在ManagementStudio没有什么本质不同。要拷贝mdf文件需要关闭所有指向mdf文件的连接。

4.正式生产运行的时候附加到SQLServer上、修改连接字符串即可,除此之外没有任何的区别,在“数据库”节点上点右键“附加”;在数据库节点上→任务→分离机可以得到可以拷来拷去的mdf文件。

5.用的时候要在控制台、WinForm项目中在Main函数最开始的位置加入下面的代码。ASP.Net项目中不需要。

string dataDir =AppDomain.CurrentDomain.BaseDirectory;

if(dataDir.EndsWith(@"\bin\Debug\") || dataDir.EndsWith(@"\bin\Release\"))

{

dataDir =System.IO.Directory.GetParent(dataDir).Parent.Parent.FullName;

AppDomain.CurrentDomain.SetData("DataDirectory",dataDir);

}

详细介绍:http://www.rupeng.com/forum/thread-11988-1-1.html
连接SQLServer:
1.连接字符串:程序通过连接字符串指定要连接哪台服务器上的、哪个实例的哪个数据库、用什么用户名密码等。

2.项目内嵌mdf文件形式的连接字符串:

"Data Source = .\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf;IntegratedSecurity=True;User Instance=True"。".\SQLEXPRESS;"表示“本机上的SQLEXPRESS实例”,如果数据库实例名不是SQLEXPRESS,则需要修改。"Database1.mdf"为mdf的文件名。

3.ADO.Net中通过SqlConnection类创建到SQLServer的连接,SqlConnection代表一个数据库连接,ADO.Net中的连接等资源都实现了IDisposable接口,可以使用using进行资源管理。执行下面的代码如果成功了就OK。

using(SqlConnection conn = newSqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf;IntegratedSecurity=True;User Instance=True"))

{

conn.Open();

Console.WriteLine("连接成功!");

}
执行简单的Insert语句:
1.SqlCommand表示向服务器提交的一个命令(SQL语句等)。

CommandText属性为要执行的SQL语句,ExecuteNonQuery方法执行一个非查询语句(Update、Insert、Delete等)

using(SqlCommand cmd =conn.CreateCommand())

{

cmd.CommandText = "Insert intoT_Users(UserName.Password) values(‘admin’,’888888’)";

cmd.ExecuteNonQuery();

}

2.ExecuteNonQuery返回值是执行的影响行数。

3.常犯的错误:

string username = "test";



cmd.CommandText = "Insert into T_Users(UserName.Password) values(username,’888888’)";

SQL语句中username与C#语句中的username是两个概念,前者是字符串””username”,后者是变量名。

注:User是关键字,故SQL语句中建议表名用T_开头,字段用F开头。
ExecuteScalar:
1.SqlCommand的ExecuteScalar方法用于执行查询,并返回查询所返回的结果集中第一行的第一列,因为不能确定返回值的类型,所以返回值是Object类型。

cmd.CommandText = "select count(*) from T_Users";

int i = Convert.ToInt32(cmd.ExecuteScalar())

cmd.CommandText = "select getdata()";

DateTime dt = Convert.ToDateTime(cmd.ExecuteScalar());

2.得到自动增长字段的主键值,在values关键词前加上output inserted.Id,其中Id为主键字段名。执行结果就是插入的主键值,用ExecuteScalar执行最方便。

cmd.CommandText = "Insertinto T_Users(UserName,Password) output inserted.Id values(‘admin’,’888888’)";

int i = Convert.ToInt32(cmd.ExecuteScalar());
执行查询ExecuteReader:
1.执行有多行结果集的用ExecuteReader

SqlDataReader reader = cmd.ExecuteReader();



while(reader.Read())

{

Console.WriteLine(reader.GetString(1));

}

2.reader的GetString、GetInt32等方法只接受整数参数,也就是序号,用GetOrdinal方法根据列名动态得到序号。

3.为什么用using:

(1)Close:关闭以后还能打开,Dispose:直接销毁,不能再次使用。using在出了作用域以后调用Dispose,SqlConnection、FileStream等的Dispose内部都会做这样的判断:判断有没有Close,如果没有Close就先Close再Dispose。

(2)自己手动Close、Dispose,如果中间处理过程发生异常,后面的Close、Dispose就不会执行了,这个连接就被占用而不释放了,如果抛几次异常后,数据库就连不上了,会报告连接次数过多之类的情况,所以用using来实现自动管理。
SQL注入漏洞攻击:
1.登录判断:select * from T_Users where UserName=… and Password=…,将参数拼接到SQL语句中。

2.构造而已的Password:1’ or ‘1’=’1

if(reader.Read())

{

Console.WriteLine("登录成功");

}

else

{

Console.WriteLine("登录失败");

}

3.防范注入漏洞攻击的办法:不适用SQL语句拼接,通过参数赋值。
查询参数:
1.SQL语句使用@UserName表示“此处用参数代替”,向SqlCommand的Parameters中添加参数:

cmd.CommandText = "select count(*) from T_Users where UserName=@UNand Password=@Pw";

cmd.Parameters.Add(new SqlParameter("UN", username));

cmd.Parameters.Add(new SqlParameter("Pw", password));

2.参数在SQLServer内部不是简单的字符串替换,SQLServer直接用添加的值进行数据比较,因此不会有注入漏洞攻击。
连接字符串:
将连接字符串写在代码中的缺点:多次重复,违反了DRY(Don't Repeat Yourself)原则;如果要修改连接字符串就要修改代码。将连接字符串写在配置文件App.Config中:

(1)添加App.config文件(文件名不能改):添加→新建项→常规→应用程序配置文件。App.config是.Net的通用配置文件,在ASP.Net中也能同样使用。

(2)在App.config中添加connectionStrings段,添加一个add项,用name属性起一个名字(比如ConnStr),connectionString属性指定连接字符串。

(3)在“引用”节点上点右键“添加引用”,找到System.configuration。不是所有.Net中的类都能直接调用,类所在的Assembly要被添加到项目的引用中才可以。

(4)ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString得到连接字符串。

数据导入导出:
1.数据导入:从文本文件导入用户信息。易错点:Parameter的重复添加。

2.数据导出:将用户信息导出到文本文件。

下面是数据导入导出的练习,老师写了导入的代码,我自己照着导入代码补上了导出的代码,最后写入文件也是用了和Console.WriteLine()方法很类似的一个格式化写入方法streamWrite.WriteLine("{0}|{1}", name, age):

private void btnImport_Click(object sender, EventArgs e)//从文件导入数据库
{
if (ofdImport.ShowDialog() != DialogResult.OK)//ShowDialog()运行对话框
{
return;
}

using (FileStream fileStream = File.OpenRead(ofdImport.FileName))//File提供用于创建、复制、删除、移动和打开文件的静态方法,OpenRead()打开现有文件进行读取
{
using (StreamReader streamReader = new StreamReader(fileStream))//StreamReader读取字符串
{
using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database2.mdf;Integrated Security=True;User Instance=True"))//创建连接时非常耗时的,因此不要每次操作都创建连接
{
conn.Open();
MessageBox.Show("打开数据库,连接成功!");
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "Insert into T_Persons(Name,Age) values(@Name,@Age)";

string line = null;
while ((line = streamReader.ReadLine()) != null)
{
string[] strs = line.Split('|');
string name = strs[0];
int age = Convert.ToInt32(strs[1]);

cmd.Parameters.Clear();//参数不能重复添加,在while中一直用的就是一个SqlCommand对象
cmd.Parameters.Add(new SqlParameter("Name", name));
cmd.Parameters.Add(new SqlParameter("Age", age));
cmd.ExecuteNonQuery();
}
}
}
}
}
MessageBox.Show("导入成功!");
}

private void btnExport_Click(object sender, EventArgs e)//从数据库导出到文件
{
if (sfdExport.ShowDialog() != DialogResult.OK)
{
return;
}

using (FileStream fileStream = File.OpenWrite(sfdExport.FileName))//OpenWrite()打开现有文件进行写入
{
using (StreamWriter streamWrite = new StreamWriter(fileStream))//StreamReader写入字符串
{
using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database2.mdf;Integrated Security=True;User Instance=True"))
{
conn.Open();
MessageBox.Show("打开数据库,连接成功!");
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "select * from T_Persons";
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string name = reader.GetString(reader.GetOrdinal("Name"));
int age = reader.GetInt32(reader.GetOrdinal("Age"));
streamWrite.WriteLine("{0}|{1}", name, age);
}
}
}
}
}
}
MessageBox.Show("导出成功!");
}


---------------------- Windows Phone 7手机开发.Net培训、期待与您交流! ----------------------详细请查看:http://net.itheima.com/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: