你的位置:首页 > ASP.net教程

[ASP.net教程]C#连接使用数据库的方法

     ASP.NET连接数据库的技术叫ADO.NET,它是用来向数据库提交sql语句的一堆类。这里连接的是Sql Server 2008数据库,其他数据库用法差不多,就是调用的类名不一样。

    首先在Web.config(本地的添加应用程序配置文件App.config,本地还要添加System.Configuration.dll程序集)上配置数据库连接字符串,添加如下节点代码:

<connectionStrings>

    <add name="connstr" connectionString="Data Source=.;Initial Catalog=Milk ;User Id=sa;Password=521521521;"></add>

 </connectionStrings>

    name是链接字符串名称,可以随便取。connectionString是链接字符串。Data Source数据库所在服务器IP地址,这里是本地写“.”。 Initial Catalog是数据库名称。User Id是数据库用户,其中sa是最高权限管理员账户,需要谨慎使用,而是针对数据库建立数据库的专用受限账户。Password是密码。

    程序使用数据库时,先提取配置文件的连接字符串赋值给一个变量。代码如下:

public static readonly string connstr =

ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;

ConfigurationManager是静态类,提供对客户端应用程序配置文件的访问。

    接着打开数据库连接,使用完毕后用using自动释放连接:

SqlConnection是个密封类,表示 SQL Server 数据库的一个打开的连接。接着是执行SQL语句,先定义向数据库发送指令用到的SqlCommand类,定义之后确定语句执行的连接对象是conn,再确定要执行的SQL语句,用法举例如下:

//SqlConnection为建立和数据库连接的对象

using(SqlConnection conn = new SqlConnection(connstr))

{

conn.Open();//打开连接

//通过连接创建一个向数据库发命令(Command)的对象SqlCommand

using(SqlCommand cmd = conn.CreateCommand())

{

cmd.CommandText =”Insert into T_Student*(Name,Age) values(‘XXX’,18)”;// CommandText要执行的SQL语句

cmd.ExecuteNonQuery();//执行

}

}

ExecuteNonQuery()一般用来执行Update、Delete、Insert语句

对于一种一行、一列返回值的结果执行用ExecuteScalar(),它返回object类型。举例如下:

using(SqlConnection conn = new SqlConnection(connstr))

{

conn.Open();//打开连接

//通过连接创建一个向数据库发命令(Command)的对象SqlCommand

using(SqlCommand cmd = conn.CreateCommand())

{

cmd.CommandText =”select Name from T_Student where Name=”XXX””;// CommandText要执行的SQL语句

cmd.ExecuteScalar();//执行

}

}

返回值有多行结果时要用ExecuteReader(),返回类型SqlDataReader,需要释放,用法举例:

using(SqlConnection conn = new SqlConnection(connstr))

{

conn.Open();//打开连接

//通过连接创建一个向数据库发命令(Command)的对象SqlCommand

using(SqlCommand cmd = conn.CreateCommand())

{

cmd.CommandText =”select * from T_Student where Age<18”;

using(SqlDataReader reader=cmd.ExecuteReader()

{

     while(reader.Read())

{

   string name=reader.GetString(1);//获得第一列列的值

   int age=reader.GetIn32(2); //获得第2列列的值

   Console.WriteLine(name);

   Console.WriteLine(age.ToString());

}

}

}

}

  其中Read方法返回bool类型,查询结果是放到数据库中,没有放到客户端。初始指针指向第一条数据之前,每调用一次Reader指针下移一条,只要没有移到最后一条之后,就直接返回true。reader的GetString\GetInt32等方法只接受整数参数,也就是序号,用GetOrdinal方法根据列名动态得到序号。

 

第0列

第一列

第二列

第三列

Id

Name

Age

Hobby

1

XXX

18

勾搭妹子

2

王旭

30

勾搭妹子

图 1   数据库T_Student表

 

   为了避免数据库注入漏洞,微软设置有查询参数,举例如下:

cmd.CommandText =”select * from T_Student where Age<@Age”;

cmd.Parameters.Add(new SqlParameter(“@Age”,19));

[email protected][email protected]关键字等。

 

    SqlDataReader是和连接相关的,SqlDataReader中的查询结果并不是放在程序中的,而是放在数据库服务器中,SqlDataReader只是相当于一个游标,指到哪里读到哪里。

    ADO.NET提供了数据集机制,DataSet,存在本地内存,其包含若干DataTable,DataTable包含若干行DataRow。使用方法:

     DataSet dataset=new DataSet();

SqlDataAdapter adapter=new SqlDataAdapter(cmd);

adapter.Fill(dataset);

SqlDataAdapter是一个帮我们把SqlCommand查询结果填充到DataSet中的类,DataSet相当于本地的list集合(小数据库)。遍历方法如下:

DataTable table=dataset.Tables[0];//一般情况下只有一个Tables,当同时执行多个select语句时有多个Tables。

DataRowCollection rows=table.Rows;

for(int i=0;i<rows.Count;i++)

{

   DataRow row=rows[i];

int age=(int)row[“Age”];//遍历年龄

}

基本上所有的步骤都是:打开链接--创建命令--执行--处理执行结果。所以可以写个公共类自己用,避免重复代码,详细代码如下:

public static class  SqlHelper

    {

        public static readonly string connstr =

            ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;

 

        public static SqlConnection OpenConnection()//建立连接

        {

            SqlConnection conn = new SqlConnection(connstr);

            conn.Open();

            return conn;

        }

 

        public static int ExecuteNonQuery(string cmdText,

            params SqlParameter[] parameters)//注意看有使用长度可变参数进行了简化

        {

            using (SqlConnection conn = new SqlConnection(connstr))

            {

                conn.Open();

                return ExecuteNonQuery(conn, cmdText, parameters);

            }

        }

 

        public static object ExecuteScalar(string cmdText,

            params SqlParameter[] parameters)

        {

            using (SqlConnection conn = new SqlConnection(connstr))

            {

                conn.Open();

                return ExecuteScalar(conn, cmdText, parameters);

            }

        }

 

        public static DataTable ExecuteDataTable(string cmdText,

            params SqlParameter[] parameters)

        {

            using (SqlConnection conn = new SqlConnection(connstr))

            {

                conn.Open();

                return ExecuteDataTable(conn, cmdText, parameters);

            }

        }

 

        public static int ExecuteNonQuery(SqlConnection conn,string cmdText,

           params SqlParameter[] parameters)

        {

            using (SqlCommand cmd = conn.CreateCommand())

            {

                cmd.CommandText = cmdText;

                cmd.Parameters.AddRange(parameters);

                return cmd.ExecuteNonQuery();//返回执行了多少行

            }

        }

 

        public static object ExecuteScalar(SqlConnection conn, string cmdText,

            params SqlParameter[] parameters)

        {

            using (SqlCommand cmd = conn.CreateCommand())

            {

                cmd.CommandText = cmdText;

                cmd.Parameters.AddRange(parameters);

                return cmd.ExecuteScalar();

            }

        }

 

        public static DataTable ExecuteDataTable(SqlConnection conn, string cmdText,

            params SqlParameter[] parameters)

        {

            using (SqlCommand cmd = conn.CreateCommand())

            {

                cmd.CommandText = cmdText;

                cmd.Parameters.AddRange(parameters);

                using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))

                {

                    DataTable dt = new DataTable();

                    adapter.Fill(dt);

                    return dt;

                }

            }

        }

 

        public static object ToDBValue(this object value)

        {

            return value == null ? DBNull.Value : value;

        }

 

        public static object FromDBValue(this object dbValue)

        {

            return dbValue == DBNull.Value ? null : dbValue;

        }

    }

封装方法的原则:把不变的放到方法里,把变化的放到参数里,SqlHelper类里返回值是一行一列的用ExecuteScaler,ExecuteNonQuery一般用来执行Update\Delete\Insert语句,ExecuteDataTable只用来执行查询结果比较少的sql,返回值是DataTable。

在数据库中NULL和“”不一样,NULL和0也不一样。数据库中NULL表示不“知道”。假如一个表中有个可空字段Name,如果有几个实例Name为NULL,

select * from T_Student where Name=NULL是查不到任何数据的。

select * from T_Student where Name is NULL可以查到所有Name填NULL的数据。

需求:如果没输入姓名,则姓名应该为NULL,如果没输入年龄,则年龄应该为NULL。

问题:在SqlParameter如果参数值为null,则表示没有提供参数的值,会报错。

解决方法:.NET提供DBNull.Value用来表示数据库中的NULL。以为DBNull.Value是object类型。所以需要这样用:

object objName;

string name=tbName.Text;

if(name.Length<0)

{

   objName=DBNull.Value;

}else

{

   objName=name;

}

接着SqlParameter参数改为objName。

同时读取数据库时,存在Null,返回给.NET的值也是DBNull.Value。所以读取后还要判断后赋值,用法如下:

if(row[“Name”]==DBNull.Value)

{

  name=null;

}

else

{

  name=(string)row[“Name”];

}

但是也有个问题,如果是int类型,则不能为null,就该定义的时候用int? age。

必须严格区分0,NULL和“”,否则出现问题很难查到。

附带上次讲的SqlHelper里的两个函数,就是对上面两个用法的封装,可以直接用在SqlParameter参数中。

 

可空数据输入数据库时用

public static object ToDBValue(this object value)

        {

            return value == null ? DBNull.Value : value;

        }

输出时用

        public static object FromDBValue(this object dbValue)

        {

            return dbValue == DBNull.Value ? null : dbValue;

        }

这个主要是用在SqlParameter中,实现可空数据的输入输出。