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

---------------------- 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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值