★★案例:书籍管理BMS
界面
基本流程
1. 创建项目BMS
2. 拖控件
Lable(lblKey),
TextBox(txtKey)
Lable(lblCate)
ComboBox(cboCate)
Button(btSearch)
DataGridView(dgvBooks)
Lable(lblI),Lable(lblID),Lable,TextBox(txtTitle),Lable,CombocBox(cboCateU),Lable,Text(txtAuthor)
Lable,TextBox(txtContent)
Button(btnAdd),Button(btnUpdate),Button(btnDel)
- 添加SqlHelper.cs类文件
a) 导入System.Configuration引用
b) 添加命名空间System.Configuration;
c) ConfigurationManager.ConnectionStrings[‘’conStr’’].connectionString;
- 4. 添加配置文件
<ConnectionString>
<add name="conStr" connectionString ="server=.;database=SimpleAriticle;Integrate Security =True;"/>
</ConnectionString>
作用:运行时,从配置文件中把name叫做conStr的这个配置文件的结点所对应的这个值(server=.;database=
SimpleAriticle;Integrate Security =True;)给读出来
内容理解
添加Book实体类:
添加这个类的作用:把表中的数据转换成书的实体,把总个表变成有意义的对象的集合(是以Object类型存储的)。
本身就是Category,只是包装成了Object而已,所以可以转化为Category,如果本身就是Object类型,则不能转。
其它:
选项控件里面有两套数据源集合,即有两种存储数据的方式。
反编译:看源码
代码
Books.cs:书籍实体类
namespace BMS
{
//书籍实体类
class Book
{
private int bId;
private int bCId;
private string bTitle;
private string bContent;
private string bAuthor;
private bool bIsDel;
private DateTime bAddtime;
private double bmoney;
private double bSubmoney;
}
}
Category.cs:书籍类别实体类
namespace BMS
{
/// <summary>
/// 书籍类别实体类
/// </summary>
public class Category
{
private int cId;
public int CId
{
get { return cId; }
set { cId = value; }
}
private string cName;
public string CName
{
get { return cName; }
set { cName = value; }
}
private string cRemark;
public string CRemark
{
get { return cRemark; }
set { cRemark = value; }
}
private bool cIsDel;
public bool CIsDel
{
get { return cIsDel; }
set { cIsDel = value; }
}
private DateTime cAddTime;
public DateTime CAddTime
{
get { return cAddTime; }
set { cAddTime = value; }
}
private int cParentId;
public int CParentId
{
get { return cParentId; }
set { cParentId = value; }
}
}
}
Form.cs
namespace BMS
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//窗体加载事件:窗体加载的同时,LoadBooks,LoadCateCbo,LoadCateCboU过程被调用实现
private void Form1_Load(object sender, EventArgs e)
{
LoadBooks();
LoadCateCbo();
LoadCateCboU();
}
/// <summary>
/// 加载书籍列表
/// </summary>
private void LoadBooks()
{
string sqlStr = "select b_id,c_name,b_title,b_content,b_author,b_addtime,b_cid from Book inner join Category on b_cid =c_cid where b_isdel=0";
DataTable dt = SqlHelper.GetDataTable(sqlStr);
dgvBooks.DataSource = dt;
}
/// <summary>
/// 加载搜索区,类别下拉框数据
/// </summary>
private void LoadCateCbo()
{
string sqlStr = "select * from Category where c_Isdel = 0";
DataTable dt = SqlHelper.GetDataTable(sqlStr);//查询未删除的分类
foreach (DataRow dr in dt.Rows)//循环生成类别实体(将行转化为实体对象)
{
Category modle = new Category();
//数据表中的某项数据有可能是Null,像下面一个可以判断
if (dr["c_id"] != null)
{
modle.CId = Convert.ToInt32(dr["c_id"]); //注意这种转化格式【前缀形式】
//convert这个类是一个转换类能将任何类型的对象转换成任何一个类型
}
modle.CName = dr["c_name"].ToString();//注意这种转换格式【后缀形式】
modle.CRemark = dr["c_remark"].ToString();
modle.CIsDel = bool.Parse(dr["c_isdel"].ToString());
modle.CAddTime = Convert.ToDateTime(dr["c_addtime"]);
modle.CParentId = Convert.ToInt32(dr["c_parentid"]);
cboCate.Items.Add(modle); //把实体对象添加到下拉框中
}
cboCate.DisplayMember = "CName";
cboCate.ValueMember = "CId";
cboCate.SelectedIndex = 0;//【效果:最初的时候,下拉框中有数据】
}
private void LoadCateCboU()//利用绑定的方式
{
string sqlStr = "select * from Category where c_Isdel = 0";
DataTable dt = SqlHelper.GetDataTable(sqlStr);//查询未删除的分类
cboCateU.DataSource = dt;
cboCateU.DisplayMember = "c_name";
cboCateU.ValueMember = "c_id";
cboCateU.SelectedIndex = 0;
}
/// <summary>
/// 搜索按钮点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSearch_Click(object sender, EventArgs e)
{
//获得关键字文本框内容,并去除两边的空格
string strKeyWord = txtKey.Text.Trim();//Trim()方法用于去掉字符串中间包含的空格
//获得下拉框选中项,转成Category类型,并获得类型ID
int cateId = ((Category)cboCateU.SelectedItem).CId;//并不是每个类型都可以转成Category【见图
string sqlStr = "select b_id,c_name,b_title,b_content,b_author,b_addtime from Book inner join Category on b_cid=c_cid where b_cid=@cid";//数据库那边的参数,下面要用到parameter
//如果关键字不为空,则向sql语句追加查询条件
if (!string.IsNullOrEmpty(strKeyWord))//字符串不为空,我们最好用【IsNullOrEmpty字段来判断】
{
sqlStr += "and b_title like '%" + strKeyWord + "%'";
}
System.Data.SqlClient.SqlParameter sp = new System.Data.SqlClient.SqlParameter("@cid", SqlDbType.Int);
DataTable dt = SqlHelper.GetDataTable(sqlStr, sp);
dgvBooks.DataSource = dt;
}
/// <summary>
/// 书籍列表的单元格点击事件方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dgvBooks_CellClick(object sender, DataGridViewCellEventArgs e)//通过事件方法的参数e可以拿到这个方法
{
int rowIndex = e.RowIndex;//选中单元格所在行的下标
string bId = dgvBooks.Rows[rowIndex].Cells[0].Value.ToString();
// dgvBooks.Rows[rowIndex]表示行集合;Cells[0]表示行集合中的第一个单元格
//所以这句表示:所在行的第一个单元格里面的值转化成成string类型;行集合
lblID.Text = bId;
txtTitle.Text = dgvBooks.Rows[rowIndex].Cells[2].Value.ToString();
txtAuthor.Text = dgvBooks.Rows[rowIndex].Cells[4].Value.ToString();
txtContent.Text = dgvBooks.Rows[rowIndex].Cells[3].Value.ToString();
cboCateU.SelectedValue = dgvBooks.Rows[rowIndex].Cells[6].Value.ToString();
}
//修改按钮点击事件
private void btnUpdate_Click(object sender, EventArgs e)
{
string cId = lblID.Text;
string bTitle = txtTitle.Text.Trim();//首先拿到书籍名称和书籍ID等内容
string bCid = cboCateU.SelectedValue.ToString();
string bAuthor = txtAuthor.Text.Trim();
string bContent = txtContent.Text.Trim();
string sqlStr = "update book set b_title=@title,b_cid=@cid;b_author=@aut,b_content=@content where b_id=@bid";
SqlParameter[] paras ={
new SqlParameter("@title",SqlDbType.Varchar),
new SqlParameter("@cid",SqlDbType.Int),
new SqlParameter("@aut",SqlDbType.VarChar),
new SqlParameter("@content",SqlDbType.VarChar),
new SqlParameter("@id",SqlDbType.Int),
};
//为参数数组中的每个参数赋值
paras[0].Value = bTitle;
paras[1].Value = bCid;
paras[2].Value = bAuthor;
paras[3].Value = bContent;
paras[4].Value = bId;
int res = SqlHelper.ExecNonQuery(sqlStr, paras);//调用SqlHelper中的非查询语句
if (res > 0)
{//如果修改成功,则刷新列表
LoadBooks();
}
else
{
MessageBox.Show("执行失败");
}
}
}
}
SqlHelper.cs
namespace BMS
{
public static class SqlHelper
{
private static string conStr = ConfigurationManager.ConnectionStrings["conStr"].ConnectionString;
private static SqlConnection conn;
/// <summary>
///连接通道属性
/// </summary>
public static SqlConnection Conn
{
get
{
if(conn==null || conn.State==ConnectionState.Broken)
{
conn=new SqlConnection(conStr);
}
return conn;
}
}
/// <summary>
/// 获取数据表
/// </summary>
/// <param name="sqlStr">查询语句</param>
/// <param name="paras">参数数组</param>
/// <returns>结果表</returns>
public static DataTable GetDataTable(string sqlStr, params SqlParameter[] paras)
{
//select * from U where id>@ddd带数据库的这种参数
//创建命令对象(查询语句,连接通道属性)
SqlCommand cmd = new SqlCommand(sqlStr, Conn);
if (paras!= null&¶s.Length > 0)//如果sql语句有参数
{
cmd.Parameters.AddRange(paras);//为命令对象添加参数数组
//foreach(SqlParameter sp in paras){
// cmd.Parameters.Add(sp);
//}//第二种方法
}
SqlDataAdapter da = new SqlDataAdapter(cmd);//查询多行数据用卡车
DataTable dt = new DataTable();
try
{
da.Fill(dt);
}
catch (Exception ex)
{
throw ex;
}
return dt;
}
/// <summary>
/// /执行非查询语句是来这里调用
/// </summary>
/// <param name="sqlStr"></param>
/// <param name="paras"></param>
/// <returns></returns>
public static void OpenDB()
{
conn.Open();
}
public static void CloseDB()
{
conn.Close();
}
public static int ExecNonQuery(string sqlStr, SqlParameter[] paras)
{//执行非查询语句是来这里调用
SqlCommand cmd = new SqlCommand(sqlStr, Conn);
if (paras != null && paras.Length > 0)
{
cmd.Parameters.AddRange(paras);
}
OpenDB();
int res = 0;
try
{
res = cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
CloseDB();
}
return res;
}
}
}
宏观简析
Book.cs
Class Book{ …… }//书籍实体类
Category.cs
Class Category{ …… }//书籍类别实体类
SqlHelper.cs
Class SqlHelper
OpenDB(){ };
CloseDB(){ };
string conStr = ConfigurationManager.ConnectionStrings[*].ConnectionString;//连接通道
SqlConnection conn;//属性中进行判断(conn==null||conn.State=ConnectionState.Broken)
DataTable GetDataTable() //获取数据表
SqlCommand cmd = ;
if(paras!=null&¶s.Length>0){……} //cmd.Parameters.AddRange(paras);
new SqlDataAdapter da = ;
new DataTable dt = ;
Fill(dt); //该处可以用try-catch
int ExecNonQuery(){ }
SqlCommand cmd = ;
if(paras!=null&¶s.Length>0){……}
OpenDB();
int res = ;
cmd.ExecuteNonQuery();//该处可以用try-catch
连接->数据表->sql命令
Form1
Form1_Load(){
LoadBooks() //加载书籍列表
string sqlStr =
DataTable dt = SqlHelper.GetDataTable(sqlStr);
dgvBooks.DataSource = dt;
LoadCateCbo() //加载搜索区,类别下拉框数据
string sqlStr =
DataTable dt = SqlHelper.GetDataTable(sqlStr);
foreach (DataRow dr in dt.Rows){ …… }//★循环生成类别实体(将行转化为实体对象)
LoadCateCboU() //利用绑定的方式
string sqlStr =
DataTable dt = SqlHelper.GetDataTable(sqlStr);
cboCateU.DataSource=dt;//关键:上面用foreach方式实现,这里一句话实现
……
btnSearch_Click() //搜索按钮点击事件
txtKey.Text.Trim()
((Category)cboCateU.SelectedItem).Cid
string sqlStr =
dgvBooks_CellClick()
e.RowIndex
dgvBooks.Rows[rowIndex].Cells[0].Value.ToString()
void btnUpdate_Click()
lblID.Text/txtTitle.Text.Trim()/cboCateU.SelectedValue.Trim()……
//首先拿到书籍名称和书籍ID等内容
sqlStr = ;
SqlParameter[] paras ={new SqlParameter()……}
paras[0…1].Value = bTitle;
if……else……
}
相应细节
txtKey.Text.Trim() //获得文本框的内容,并用Trim方法用于去掉字符串中间包含的空格
((Category)cboCateU.SelectedItem).Cid //获得下拉框选中项,转成Category类型,并获得类型ID
IsNullOrEmpty 用于判断字符串是否为空
SelectedIndex=0; //使下拉框中最初是有数据的
e.RowIndex; //选中单元格所在行的下标
dgvBooks.DataSource //DataSource是数据绑定控件,用于指定数据源,比较常用的是DataTable
//DataSource 可以是任何 System.Collections.IEnumerable 对象,
关于DataSource
conn.State //连接状态
cmd.Parameters.AddRange(paras);//为命令对象添加参数数组