机房重构中,组合查询也是一个让人头疼的难点,其实说难也只是因为自己没有理清头绪,没有开始。如果自己理清了关系,并着手开始,然后一点一点攻克,最后当功能实现,代码顺利跑起来的那一刻,会觉得其实一不过如此,哈哈。所以,总结两个字,去做!
一、基本介绍
本着机房重构实践模式的原则,组合查询用到了模版模式。
模板模式属于行为型模式,其意图是定义一个操作的算法骨架,而将一些步骤延迟到子类中,可以不改变一个算法的结构即可以重新定义概算法的某些特定步骤。
直白的理解,模版模式就是先准备一个模子,然后需要做的只是把原料倒到模子里,再加工加工就ok了,这样就省去了很多重复的过程,放到代码里说,就是实现了复用,减少了代码的重复。
二、具体实现
1、建立模版父窗体
以上是制作的一个模版父窗体,即添加一个windows窗体,设计模版界面,然后在模版窗体里写抽象出来的类和方法的代码。
UI层代码
public partial class OpGFa : Form
{
public OpGFa()
{
InitializeComponent();
}
Entity.GroupInquiryEntity groupentity = new Entity.GroupInquiryEntity();
public void OpGFa_Load(object sender, EventArgs e)
{
//将参数传递给实体,赋初值
//因为不同的窗体字段不同,所以赋空,子窗体重写
groupentity.fileds1 = "";
groupentity.fileds2 = "";
groupentity.fileds3 = "";
//操作符
cmboperator1.Items.Add(">");
cmboperator1.Items.Add("<");
cmboperator1.Items.Add("=");
cmboperator1.Items.Add("<>");
cmboperator2.Items.Add(">");
cmboperator2.Items.Add("<");
cmboperator2.Items.Add("=");
cmboperator2.Items.Add("<>");
cmboperator3.Items.Add(">");
cmboperator3.Items.Add("<");
cmboperator3.Items.Add("=");
cmboperator3.Items.Add("<>");
//关系
cmbrelation1.Items.Add("");
cmbrelation1.Items.Add("与");
cmbrelation1.Items.Add("或");
cmbrelation2.Items.Add("");
cmbrelation2.Items.Add("与");
cmbrelation2.Items.Add("或");
//窗体加载后,后两组控件默认不可用
cmbfields2.Enabled = false;
cmbfields3.Enabled = false;
cmboperator2.Enabled = false;
cmboperator3.Enabled = false;
cmbrelation2.Enabled = false;
txtInquiry2.Enabled = false;
txtInquiry3.Enabled = false;
}
//优化控件可用性
//组合关系1不为空后,显示第二行查询条件
public void cmbrelation1_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbrelation1.Text == "")
{
cmbfields2.Enabled = false;
cmbfields3.Enabled = false;
cmboperator2.Enabled = false;
cmboperator3.Enabled = false;
cmbrelation2.Enabled = false;
txtInquiry2.Enabled = false;
txtInquiry3.Enabled = false;
}
else
{
cmbfields2.Enabled = true;
cmboperator2.Enabled = true;
cmbrelation2.Enabled = true;
txtInquiry2.Enabled = true;
}
}
//组合关系2不为空后,显示第三行查询条件
public void cmbrelation2_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbrelation2.Text == "")
{
cmbfields3.Enabled = false;
cmboperator3.Enabled = false;
txtInquiry3.Enabled = false;
}
else
{
cmbfields3.Enabled = true;
cmboperator3.Enabled = true;
txtInquiry3.Enabled = true;
}
}
public void btnOK_Click(object sender, EventArgs e)
{
//第一行组合关系为空
if (cmbrelation1.Text == "")
{
if (cmbfields1.Text == ""||cmboperator1.Text == "" ||txtInquiry1.Text == "" )
{
MessageBox.Show("第一行查询条件不能为空,请完善查询信息!");
}
}
//当第一个组合关系不为空时
if (cmbrelation1.Text != "")
{
if (cmbfields1.Text == ""||cmboperator1.Text == "" ||txtInquiry1.Text == "" || cmbfields2.Text == ""||cmboperator2.Text == "" ||txtInquiry2.Text == "")
{
MessageBox.Show("前两行信息不能为空,请完善查询信息!");
}
}
//当第二个组合关系不为空,则判断所有文本框是否为空
if (cmbrelation2.Text != "")
{
if (cmbfields1.Text == ""||cmboperator1.Text == "" ||txtInquiry1.Text == "" || cmbfields2.Text == ""||cmboperator2.Text == "" ||txtInquiry2.Text == ""||cmbfields3.Text == ""||cmboperator3.Text == "" ||txtInquiry3.Text == "")
{
MessageBox.Show("信息不能为空,请完善查询信息!");
}
}
//将参数传递给实体
groupentity.fileds1 = ToName(cmbfields1.Text);
groupentity.fileds2 = ToName(cmbfields2.Text);
groupentity.fileds3 = ToName(cmbfields3.Text);
groupentity.operator1 = cmboperator1.Text;
groupentity.operator2 = cmboperator2.Text;
groupentity.operator3 = cmboperator3.Text;
groupentity.context1 = txtInquiry1.Text;
groupentity.context2 = txtInquiry2.Text;
groupentity.context3 = txtInquiry2.Text;
groupentity.relation1 = ToName(cmbrelation1.Text);
groupentity.relation2 = ToName(cmbrelation2.Text);
groupentity.tableName = GetTable();
//实例化外观,将查询到的数据表显示到控件中
Facade.OpFacade facade = new Facade.OpFacade();
DataTable table = facade.groupInquiry(groupentity);
if (table.Rows.Count > 0)
{
dataGridView1.DataSource = table;
}
else
{
MessageBox.Show("没有记录,请重新设计查询条件");
}
}
//模版方法
//定义虚函数ToName,将查询的内容转换成数据库的列名称
public virtual string ToName(string combo)
{
return "";
}
//获得数据库名称
public virtual string GetTable()
{
return "";
}
//把表显示到datagrideview中
protected virtual void Todgv()
{
}
//关闭该窗体
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
}
D层代码
//组合查询有D层代码可知我用到了存储过程,来实现复杂的查询,存储过程如下:
public DataTable groupInquiry(Entity.GroupInquiryEntity groupentity)
{
SqlHelper.sqlhelper sqlhelper = new SqlHelper.sqlhelper();
SqlParameter[] sqlparams = {
new SqlParameter("@fileds1",groupentity.fileds1),
new SqlParameter("@fileds2",groupentity.fileds2),
new SqlParameter("@fileds3",groupentity.fileds3),
new SqlParameter("@operator1",groupentity.operator1),
new SqlParameter("@operator2",groupentity.operator2),
new SqlParameter("@operator3",groupentity.operator3),
new SqlParameter("@context1",groupentity.context1),
new SqlParameter("@context2",groupentity.context2),
new SqlParameter("@context3",groupentity.context3),
new SqlParameter("@relation1",groupentity.relation1),
new SqlParameter("@relation2",groupentity.relation2),
new SqlParameter("@tableName",groupentity.tableName)
};
string sql = "PROC_GroupInquiry";
DataTable table = SqlHelper.sqlhelper.GetDataTable(sql, CommandType.StoredProcedure, sqlparams);
return table;
}
-- =============================================
-- Author:吕德彪
-- Create date: 2017/6/10
-- Description:组合查询
-- =============================================
ALTER PROCEDURE [dbo].[PROC_GroupInquiry]
-- Add the parameters for the stored procedure here
@fileds1 varchar(10),
@fileds2 varchar(10),
@fileds3 varchar(10),
@operator1 varchar(10),
@operator2 varchar(10),
@operator3 varchar(10),
@context1 varchar(10),
@context2 varchar(10),
@context3 varchar(10),
@relation1 varchar(10),
@relation2 varchar(10),
@tableName varchar(20)
AS
declare @TempSql varchar(500)--临时存放sql语句
BEGIN
SET @TempSql='SELECT * FROM '+@tableName +' WHERE ' +@fileds1 +@operator1+char(39) + @context1 + char(39)
if (@relation1 != '')
BEGIN
SET @TempSql=@TempSql+@relation1+CHAR(32)+@fileds2 +@operator2+CHAR(39)+@context2+CHAR(39)
if (@relation2 != '')
BEGIN
SET @TempSql=@TempSql+@relation2+CHAR(32)+@fileds3+@operator3+CHAR(39)+@context3+CHAR(39)
END
END
EXECUTE(@TempSql)
END
2、建立子窗体
如上图建立子窗体,选择继承创建的父窗体模板,然后就可以得到一模一样的子窗体了。通过在子窗体里重写一些方法和类,以实现不同的功能就可以了。
实现工作记录查询的代码如下:
public partial class OpGWorkRecord : LoginUI.OpGFa
{
public OpGWorkRecord()
{
InitializeComponent();
}
private void OpGWorkRecord_Load(object sender, EventArgs e)
{
string[] fileName2 = { "教师", "登录日期", "登录时间", "注销日期", "注销时间", "机器名", "状态" };
cmbfields1.Items.AddRange(fileName2);
cmbfields2.Items.AddRange(fileName2);
cmbfields3.Items.AddRange(fileName2);
}
public override string ToName(string combo)
{
switch (combo)
{
case "教师":
return "UserID";
case "登录日期":
return "loginDate";
case "登录时间":
return "loginTime";
case "注销日期":
return "logoutDate";
case "注销时间":
return "logoutTime";
case "机器名":
return "computer";
case "状态":
return "status";
case "或":
return "or";
case "与":
return "and";
default:
return "";
}
}
//返回数据库
public override string GetTable()
{
return "WorkLog_Info";
}
}
三、总结
刚开始做确实无从下手,但是只要开始了,慢慢摸索,慢慢实践,整个过程就会慢慢的变得越来越完善,Just To Do!