经过重重困难终于把机房重构的三大难点之一的组合查询给解决了,今天小编和大家分享一下组合查询过程中的难点和需要注意的地方。
首先我们来了解一下什么是‘组合查询’,所谓查询我们都知道,就是通过sql语句通过DAL层传递的参数查找数据并返回。这是简单的查询,而组合查询的意思就如字面所知,将我要查询的条件组合起来,组合成我们需求的查询语句再去查询。
至此,我们可以了解到这里的难点包括(条件的组合,sql语句的拼接),接下来我们就一点一点的解决问题,循环渐进。
首先我们要做的就是完成多种条件的拼接,我们通过虚方法的重写,来转换数据库字段,把我们在UI层得到的string类型数据转换成我们想要的数据库的字段,用模版方法写好父模版,所有的其他组合查询都继承子窗体,重写虚方法发,添加各自不同的字段。
///父窗体代码
namespace UI
{
public partial class frmGroupFind : Form
{
public frmGroupFind()
{
InitializeComponent();
}
Entity.GroupFind enGroupFind = new Entity.GroupFind();//实例化实体
private void frmMdiStuInfo_Load(object sender, EventArgs e)
{
// TODO: 这行代码将数据加载到表“jiFangChongGouDataSet2.Student_Info”中。您可以根据需要移动或删除它。
//this.student_InfoTableAdapter.Fill(this.jiFangChongGouDataSet2.Student_Info);
#region//操作符
CmbMark1.Items.Add(">");
CmbMark1.Items.Add("<");
CmbMark1.Items.Add("=");
CmbMark1.Items.Add("<>");
CmbMark2.Items.Add(">");
CmbMark2.Items.Add("<");
CmbMark2.Items.Add("=");
CmbMark2.Items.Add("<>");
CmbMark3.Items.Add(">");
CmbMark3.Items.Add("<");
CmbMark3.Items.Add("=");
CmbMark3.Items.Add("<>");
#endregion
#region//关系符号
CmbRelation1.Items.Add("与");
CmbRelation1.Items.Add("或");
CmbRelation2.Items.Add("与");
CmbRelation2.Items.Add("或");
#endregion
#region//设置控件不可用状态
CmbMark2.Enabled = false;
CmbMark3.Enabled = false;
CmbName2.Enabled = false;
CmbName3.Enabled = false;
CmbRelation2.Enabled = false;
txtInfo2.Enabled = false;
txtInfo3.Enabled = false;
dtp1.Visible = false;
dtp2.Visible = false;
dtp3.Visible = false;
#endregion
#region//设置复选框只可以选择不可以输入
this.CmbMark1.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbMark2.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbMark3.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbName1.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbName2.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbName3.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbRelation1.DropDownStyle = ComboBoxStyle.DropDownList;
this.CmbRelation2.DropDownStyle = ComboBoxStyle.DropDownList;
#endregion
}
#region//自己构造的虚方法
public virtual string ToName(string combo)//将字段转化为数据库字段
{
return "";
}
protected virtual string Getdbtable()//获得数据库名称
{
return "";
}
protected virtual void ToDgv(Entity.GroupFind enGroupFind)//显示数据
{
}
#endregion
private void btnSearch_Click(object sender, EventArgs e)
{
//主要完成输入内容的转换和拼接
//判空
if (CmbRelation1.Text=="")
{
if (CmbName1.Text == "" || CmbMark1.Text == "" || txtInfo1.Text == "")
{
MessageBox.Show("第一行查询条件为空,请添加条件");
}
}
if (CmbRelation1.Text!="")
{
if (CmbName1.Text==""||CmbMark1.Text==""||txtInfo1.Text==""||CmbName2.Text==""||CmbMark2.Text==""||txtInfo2.Text=="")
{
MessageBox.Show("输入的查询条件为空,请添加条件");
}
}
if (CmbRelation2.Text!="")
{
if (CmbName1.Text==""||CmbMark1.Text==""||txtInfo1.Text==""||CmbName2.Text==""||CmbMark2.Text==""||txtInfo2.Text==""||CmbName3.Text == "" || CmbMark3.Text == "" || txtInfo3.Text == "")
{
MessageBox.Show("输入的查询条件为空,请添加条件");
}
}
//给实体赋值
enGroupFind.CmbName1 = ToName(CmbName1.Text.Trim());
enGroupFind.CmbName2 = ToName(CmbName2.Text.Trim());
enGroupFind.CmbName3 = ToName(CmbName3.Text.Trim());
enGroupFind.CmbOper1 = CmbMark1.Text.Trim();
enGroupFind.CmbOper2 = CmbMark2.Text.Trim();
enGroupFind.CmbOper3 = CmbMark3.Text.Trim();
enGroupFind.CmbGroup1 = ToName(CmbRelation1.Text.Trim());
enGroupFind.CmbGroup2 = ToName(CmbRelation2.Text.Trim());
enGroupFind.txtInfo1 = txtInfo1.Text.Trim();
enGroupFind.txtInfo2 = txtInfo2.Text.Trim();
enGroupFind.txtInfo3 = txtInfo3.Text.Trim();
enGroupFind.GetDataTable = Getdbtable();//从数据库中获取表格(选择调用那个数据库)
Facade.GroupFindFacade groupFind = new Facade.GroupFindFacade();//实例化传参
DataTable result = new DataTable();
result = groupFind.GroupCheck(enGroupFind);//接收返回值
if (result.Rows.Count == 0)//没有查询到
{
MessageBox.Show("没有复合条件的记录,请重新选择条件");
}
else
{
ToDgv(enGroupFind);//查询到以后调用子窗体中重写的方法显示数据
}
}
private void CmbRelation1_SelectedIndexChanged(object sender, EventArgs e)
{
if (CmbRelation1.Text!="")//第一和组合条件不为空
{
CmbName2.Enabled = true;
CmbMark2.Enabled = true;
txtInfo2.Enabled = true;
}
}
private void CmbRelation2_SelectedIndexChanged(object sender, EventArgs e)
{
if (CmbRelation2.Text!="")
{
CmbName3.Enabled = true;
CmbMark3.Enabled = true;
txtInfo3.Enabled = true;
}
}
private void btnClear_Click(object sender, EventArgs e)
{
this.Close();
}
private void fillByToolStripButton_Click(object sender, EventArgs e)
{
try
{
this.student_InfoTableAdapter.FillBy(this.jiFangChongGouDataSet2.Student_Info);
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
}
所谓模版方法就是,写好一个模版,在其他地方需要用的类似的东西,直接继承,然后有需要的方法重写,其他公共的则继承
如何创建继承窗体呢?
//子窗体
public partial class OperatorDroupFind : UI.frmGroupFind
{
public OperatorDroupFind()
{
InitializeComponent();
}
public override string ToName(string combo)//重写虚方法,将自己要的字段转化成数据库字段
{
switch (combo)
{
case "卡号":
return "cardNo";
case "学号":
return "StudentNo";
case "姓名":
return "StudentName";
case "性别":
return "Sex";
case "专业":
return "Department";
case"与":
return "and";
case"或":
return "or";
default:
return "";
}
}
protected override string Getdbtable() //Select语句需求的数据库
{
return "Student_Info";
}
protected override void ToDgv(Entity.GroupFind enGroupFind)//重写方法,显示结果
{
dataGridView1.DataSource = "";
DataTable dt = new DataTable();
Facade.GroupFindFacade gf = new Facade.GroupFindFacade();//去拿到数据库的数据
dt = gf.GroupCheck(enGroupFind);
if (dt.Rows.Count==0)
{
MessageBox.Show("没有记录,请重新查询");
}
else
{
//子类中的需要的东西,父窗体只负责显示
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
}
}
private void CmbMark1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void CmbName1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void btnSearch_Click(object sender, EventArgs e)
{
////给实体传值
//Entity.GroupFind enGroupFind = new Entity.GroupFind()
//{
// CmbName1 = ToName(CmbName1.Text),
// CmbName2 = ToName(CmbName2.Text),
// CmbName3 = ToName(CmbName3.Text),
// CmbOper1 = CmbMark1.Text.Trim(),
// CmbOper2 =CmbMark2.Text.Trim(),
// CmbOper3 = CmbMark3.Text.Trim(),
// CmbGroup1 = ToName(CmbRelation1.Text),
// CmbGroup2 = ToName(CmbRelation2.Text),
// txtInfo1 = txtInfo1.Text.Trim(),
// txtInfo2 = txtInfo2.Text.Trim(),
// txtInfo3 = txtInfo3.Text.Trim(),
// GetDataTable = Getdbtable()//从数据库中获取表格
//};
//Facade.GroupFindFacade groupfind = new Facade.GroupFindFacade();
//DataTable result = new DataTable();
//result = groupfind.GroupCheck(enGroupFind);
}
private void OperatorDroupFind_Load(object sender, EventArgs e)
{
this.Text = "学生信息";
CmbName1.Items.Add("卡号");
CmbName1.Items.Add("学号");
CmbName1.Items.Add("姓名");
CmbName1.Items.Add("性别");
CmbName1.Items.Add("专业");
CmbName2.Items.Add("卡号");
CmbName2.Items.Add("学号");
CmbName2.Items.Add("姓名");
CmbName2.Items.Add("性别");
CmbName2.Items.Add("专业");
CmbName3.Items.Add("卡号");
CmbName3.Items.Add("学号");
CmbName3.Items.Add("姓名");
CmbName3.Items.Add("性别");
CmbName3.Items.Add("专业");
}
}
我们上面解决了如何把字段转化成数据库字段,也在DAL层完成了传参,接下来就是我们的存储过程了。
第二个问题,我们要将sql语句拼凑成我们想要的,在这我们还是借助存储过程。接下来我们一起来看看,存储过程的思路和要注意的点。
//存储过程
USE [JiFangChongGou]
GO
/****** Object: StoredProcedure [dbo].[PROC_GroupFind] Script Date: 08/16/2018 11:22:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
-- Description: <组合查询>
-- =============================================
ALTER PROCEDURE [dbo].[PROC_GroupFind]
-- Add the parameters for the stored procedure here
@CmbName1 varchar(50),
@CmbName2 varchar(50),
@CmbName3 varchar(50),
@CmbOper1 varChar(10),
@CmbOper2 varChar(10),
@CmbOper3 varChar(10),
@CmbGroup1 varchar(50),
@CmbGroup2 varchar(50),
@GetDataTable varchar(50),
@txtInfo1 varchar(50),
@txtInfo2 varchar(50),
@txtInfo3 varchar(50)
AS
declare @TempSql varchar(500)--临时存放Sql语句
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET @TempSql='Select * from '+@GetDataTable+' Where'+CHAR(32)+@CmbName1+@CmbOper1 +CHAR(39)+@txtInfo1 +CHAR(39)
if (@CmbGroup1!='')
BEGIN
SET @TempSql =@TempSql +CHAR(32) +@CmbGroup1 +CHAR(32)+@CmbName2 +@CmbOper2 +CHAR(39)+@txtInfo2 +CHAR(39)
if (@CmbGroup2!='')
begin
SET @TempSql =@TempSql +CHAR(32)+@CmbGroup2 +CHAR(32)+@CmbName3 +@CmbOper3 +CHAR(39)+@txtInfo3 +CHAR(39)
end
END
exec(@TempSql)
END
存储过程中最重要的就是sql语句的拼接,当然在这里也有许多没注意到的东西,下面我们来一起来看一看
首先我们看我们需要不同的几种条件所以我们xi先定义一个@Tempsql来存储
SET @TempSql='Select * from '+@GetDataTable+' Where'+CHAR(32)+@CmbName1+@CmbOper1 +CHAR(39)+@txtInfo1 +CHAR(39)
看这一行代码,第一个要注意的地方在于'from'的右边和'WHERE'的左边必须要添加空格,如果不加空格会报一些类似于找不到ca参数的错误。
第二点要注意的地方:
SET @TempSql =@TempSql +CHAR(32) +@CmbGroup1 +CHAR(32)+@CmbName2 +@CmbOper2 +CHAR(39)+@txtInfo2 +CHAR(39)
我们看到其中有CHAR(32)+参数,其实在这里把他们两个看做了一个整体,我们需要连接整体的时候在(+CHAR(32)+参数)的前面加入空格。
以至于具体为什么这样可以自己去了解一下sql语句。今天组合查询的分享就到此结束了,本人C#小白,如果有什么问题,还希望ge各位大佬多多指点。