asp.net通用查询模块设计

前言

自从上次狂喷了devexpress for asp.net面向互联网的app的各种不合理,好像骂的dev无处容身了,不过说实话,dev在做互联网的app时,生成的代码确实很多,在服务器解析方面,效率肯定不是很高的,这是使用过dev控件的伙计们都有目共睹之处。难道一款被微软官方推荐的dev真他妈的就这么烂吗?我看未必,好钢你得用到刀刃上,你想杀只老母鸡吃,但是你要用棒槌把鸡打死了再煮,估计鸡死了也就成了肉酱了,那这只鸡杀的就太没水准了,你得用锋利的小刀割了老母鸡喉咙便是。使用dev做内网的一些应用,那才叫高效率,样式丰富,统一,大方,美观,是不可多得的选择。

功能介绍

今天闲暇,做一点学习笔记,针对asp.net的通用查询做了一个查询模块,代码可能略有粗糙,见谅。这里我要讲讲为什么在asp.net里为什么要用通用查询,这里我是有原因的。

  • 查询字段比较多时,为了在页面不占用太大空间
  • 查询字段容易变更,为了维护方便,不用更改主程序代码
  • 主表子表孙表以及以下节点的字段都可能需要查询,提供更灵活的支持

以上是预览图片,左边下拉是字段,右边依次是比较符,比较值,增加条件(and),或条件(or),取消,清空当前选择的字段比较符信息,清楚所有条件

中间显示的是每次操作增加,或,清楚后的条件数据绑定,这里用的是Repeater

查询:将条件输出到页面

这里的查询字段根据业务需要归纳为以下比较类型

  • formNo:用于单号等字段比较,对应sql: where FormNo=’’
  • string:用于字符串模糊查询,对应sql: where ClientName like ‘%凡客%’
  • date:用于日期比较,对应>=,<=,=
  • select:用于状态等类似字段比较,其实就是=,只不过是用下拉框显示

有了以上基础,当前端操作条件组合时,后台产生对应的sql拼接

设计

具体问题,具体分析,怎么样才能从面向对象的角度更清晰的设计出模块功能呢?首先我们来分解:

一个查询字段包含如下信息:

  • fieldName:字段名,如ClientName
  • caption:前端显示名,如客户名称
  • dataType:业务数据类型,如like
  • groupSeq:组别序号,如1,这里指的是表的级别,可以自定义,例如客户表是主表,那么客户下面可能有对应的产品,产品下面又对应很多参数,这里的组别ID根据需要自定义

那么我们可以把这些条件信息用以下xml来表示

例如:

字段配置

<fields>
<field name="Req_No" caption="申请单号" dataType="formNo" groupSeq="1" />
<field name="Operate_Time" caption="送检日期" dataType="date" groupSeq="1" />
<field name="Send_CustName" caption="委托单位" dataType="string" groupSeq="1" />
<field name="NULL" caption="区域" dataType="select" groupSeq="1" >
<items>
<item value="Local_Name = 'BJ'" text="北京" />
<item value="Local_Name = 'CQ'" text="重庆" />
<item value="Local_Name = 'SH'" text="上海" />
</items>
</field>
</fields>

ok,字段属性就这么多了,比较符也很简单

 比较符配置

<operators dataType="formNo">
<operator value="equal" text="等于" dbValue="=" selected="true" />
</operators>
<operators dataType="select">
<operator value="equal" text="等于" dbValue="=" selected="true" />
</operators>
<operators dataType="number">
<operator value="equal" text="等于" dbValue="=" selected="true" />
</operators>
<operators dataType="string">
<operator value="equal" text="等于" dbValue="=" selected="false" />
<operator value="contains" text="包含" dbValue="like" selected="true" />
<operator value="notContains" text="不包含" dbValue="not like" selected="false" />
</operators>
<operators dataType="date">
<operator value="equal" text="等于" dbValue="=" selected="false" />
<operator value="more_equal" text="大于等于" dbValue="&gt;=" selected="true" />
<operator value="less_equal" text="小于等于" dbValue="&lt;=" selected="false" />
</operators>

以上是配置文件的设计,前端借助dev的华丽丽的样式,也毫不费功夫

 .aspx

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table>
<tr>
<td>
<dx:ASPxComboBox ID="cbField" runat="server" AutoPostBack="True" OnSelectedIndexChanged="cbField_SelectedIndexChanged">
</dx:ASPxComboBox>
</td>
<td>
<dx:ASPxComboBox ID="cbOperator" runat="server" ValueType="System.String" Width="80px"
OnSelectedIndexChanged="cbOperator_SelectedIndexChanged">
</dx:ASPxComboBox>
</td>
<td>
<dx:ASPxTextBox ID="txtValue" runat="server" Width="170px">
</dx:ASPxTextBox>
<dx:ASPxComboBox ID="cbValue" runat="server" Visible="false" ValueType="System.String">
</dx:ASPxComboBox>
<dx:ASPxDateEdit ID="dtValue" runat="server" Visible="false">
</dx:ASPxDateEdit>
</td>
<td>
<dx:ASPxButton ID="btnAdd" runat="server" Text="增加" Width="60" ClientInstanceName="btn_Cdt_Add"
OnClick="btnAdd_Click">
</dx:ASPxButton>
</td>
<td>
<dx:ASPxButton ID="btnOr" runat="server" Text="或" Width="60" ClientInstanceName="btn_Cdt_Or"
OnClick="btnOr_Click">
</dx:ASPxButton>
</td>
<td>
<dx:ASPxButton ID="btnCancel" runat="server" Text="取消" Width="60" ClientInstanceName="btn_Cdt_Cancel"
OnClick="btnCancel_Click">
</dx:ASPxButton>
</td>
<td>
<dx:ASPxButton ID="btnClear" runat="server" Text="清除" Width="60" ClientInstanceName="btn_Cdt_Clear"
OnClick="btnClear_Click">
</dx:ASPxButton>
</td>
</tr>
<tr>
<td colspan="3">
<asp:Repeater ID="rpConditionList" runat="server">
<ItemTemplate>
<table>
<tr>
<td>
<dx:ASPxLabel ID="ASPxLabel3" runat="server" Text='<%# Eval("Index") %>' Visible="false" />
<dx:ASPxLabel ID="lblRelation" runat="server" Text='<%# Eval("Relation") %>' />
<dx:ASPxLabel ID="lblCondition" runat="server" Text='<%# Eval("Caption") %>' />
<dx:ASPxLabel ID="ASPxLabel1" runat="server" Text='<%# Eval("Operator.Text") %>' />
<dx:ASPxLabel ID="ASPxLabel2" runat="server" Text='<%# Eval("Value") %>' />
</td>
<td>
<dx:ASPxButton ID="btnDelete" runat="server" OnClick="btnDelete_Click" CommandArgument='<%# Eval("Index") %>'
Text="×" Width="20" Height="20" />
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
</td>
<td>
&nbsp;
</td>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>

以上字段控件只需要3个,TextBox,ComboBox,DateEdit

Repeater用来显示组合后的条件

ok,配置和前端搞定,我们来写后台代码

字段实体和操作符实体类,以及用到的枚举

 Entity&Enum

 public class CdtEntity
{
public CdtEntity() { }
public CdtEntity(string field, string caption, string dataType, int groupSeq, List<Operator> operatorList, object value)
{
this.Field = field;
this.Caption = caption;
this.DataType = dataType;
this.GroupSeq = groupSeq;
this.OperatorList = operatorList;
this.Value = value;
}
public CdtEntity(int index, string field, string caption, string dataType, int groupSeq, Operator _operator, object input, string relation)
{
this.Index = index;
this.Field = field;
this.Caption = caption;
this.DataType = dataType;
this.GroupSeq = groupSeq;
this.Operator = _operator;
this.Value = input;
this.Relation = relation;
}
public CdtEntity Copy(CdtEntity cdtEntity)
{
CdtEntity model = new CdtEntity();
model.Field = cdtEntity.Field;
model.Caption = cdtEntity.Caption;
model.DataType = cdtEntity.DataType;
model.Operator = cdtEntity.Operator;
model.OperatorList = cdtEntity.OperatorList;
model.Value = cdtEntity.Value;
model.Relation = cdtEntity.Relation;
model.Index = cdtEntity.Index;
model.GroupSeq = cdtEntity.GroupSeq;
return model;
}
public string Field { get; set; }
public string Caption { get; set; }
public string DataType { get; set; }
public Operator Operator { get; set; }
public List<Operator> OperatorList { get; set; }
public object Value { get; set; }
/// <summary>
/// 条件关联符号:and or
/// </summary>
public string Relation { get; set; }
/// <summary>
/// 索引
/// </summary>
public int Index { get; set; }
/// <summary>
/// 组序号
/// </summary>
public int GroupSeq { get; set; }
}
/// <summary>
/// 操作符
/// </summary>
public class Operator
{
public Operator() { }
public Operator(string value, string text, string dbValue, bool selected)
{
this.Value = value;
this.Text = text;
this.DbValue = dbValue;
this.Selected = selected;
}
public string Value { get; set; }
public string Text { get; set; }
public string DbValue { get; set; }
public bool Selected { get; set; }
}
/// <summary>
/// 下拉框数据实体
/// </summary>
public class Item
{
public string Value { get; set; }
public string Text { get; set; }
}
/// <summary>
/// 操作符枚举
/// </summary>
public enum Enum_Operator
{
等于 = 1,
不等于 = 2,
大于 = 3,
大于等于 = 4,
小于 = 5,
小于等于 = 6
}
/// <summary>
/// 数据类型
/// </summary>
public enum DataType
{
FormNo = 1,
String = 2,
Number = 3,
Date = 4,
Select = 5
}

因为这里用的dev服务器控件,所以在字段选择改变后,要执行后台事件,要做的事情就是将该字段配置所属的数据类型下的比较符加载出来,并根据数据类型改变填写值的控件

点击增加按钮时将当前字段的信息存入CdtEntity实体对象,并添加到List<CdtEntity>集合,然后拼接成SQL字符串,这里加List集合的原因是为了处理更方便,因为加的字段条件也要进行增删操作

以下将核心代码都贴出来,当然有的地方写的有点冗余了,后面改改吧,主要是为了分享这种思想,刚接触asp.net的童鞋们可以看看,大牛们可以绕道了。

 业务代码

  #region 输入参数
public string ConfigPath
{
get
{
return Convert.ToString(ViewState["ConfigPath"]);
}
set
{
ViewState["ConfigPath"] = value;
}
}
#endregion #region 输出参数
public string StrWhere
{
get
{
return Convert.ToString(ViewState["StrWhere"]);
}
set
{
ViewState["StrWhere"] = value;
}
}
#endregion #region 属性
/// <summary>
/// 输出类型对应的比较符集合
/// string:dataType
/// List<Operator>:比较符集合
/// </summary>
private Dictionary<string, List<Operator>> Operators
{
get
{
return ViewState["Operators"] as Dictionary<string, List<Operator>>;
}
set
{
ViewState["Operators"] = value;
}
}
/// <summary>
/// 初始化字段信息
/// </summary>
private List<CdtEntity> CdtEntityList
{
get
{
return ViewState["CdtEntityList"] as List<CdtEntity>;
}
set
{
ViewState["CdtEntityList"] = value;
}
} /// <summary>
/// 当前选择字段信息
/// </summary>
private CdtEntity CurrentCdtEntity
{
get
{
return ViewState["CurrentCdtEntity"] as CdtEntity;
}
set
{
ViewState["CurrentCdtEntity"] = value;
}
} /// <summary>
/// 当前比较符
/// </summary>
private Operator CurrentOperator
{
get
{
return ViewState["CurrentOperator"] as Operator;
}
set
{
ViewState["CurrentOperator"] = value;
}
} /// <summary>
/// 构造的查询条件集合
/// </summary>
private List<CdtEntity> StrWhereList
{
get
{
return ViewState["StrWhereList"] as List<CdtEntity>;
}
set
{
ViewState["StrWhereList"] = value;
}
}
#endregion #region 页面事件
/// <summary>
/// 字段选择索引改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void cbField_SelectedIndexChanged(object sender, EventArgs e)
{
this.cbOperator.Items.Clear();
string selectedValue = (sender as ASPxComboBox).Value.ToString();
CdtEntity entity = CdtEntityList.Where(c => c.Field == selectedValue).FirstOrDefault();
CurrentCdtEntity = entity;
ListEditItem editItem;
int selectedIndex = 0;
foreach (var item in entity.OperatorList)
{
editItem = new ListEditItem(item.Text, item.Value);
this.cbOperator.Items.Add(editItem);
if (item.Selected)
{
cbOperator.SelectedIndex = selectedIndex;
CurrentOperator = new Operator(cbOperator.Value.ToString(), cbOperator.Text, item.DbValue, false);
}
selectedIndex++;
}
switch (entity.DataType)
{
case "formNo":
case "number":
case "string":
txtValue.Visible = true;
dtValue.Visible = false;
cbValue.Visible = false;
break;
case "date":
txtValue.Visible = false;
dtValue.Visible = true;
cbValue.Visible = false;
break;
case "select":
txtValue.Visible = false;
dtValue.Visible = false;
cbValue.Visible = true;
cbValue.Items.Clear();
foreach (Item item in (List<Item>)entity.Value)
{
cbValue.Items.Add(item.Text, item.Value);
}
break;
default:
break;
} txtValue.Text = "";
cbValue.SelectedIndex = -1;
}
/// <summary>
/// 操作符改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void cbOperator_SelectedIndexChanged(object sender, EventArgs e)
{
string dbValue = "";
switch (cbOperator.Value.ToString())
{
case "equal":
dbValue=" = ";
break;
case "contains":
dbValue = " like ";
break;
case "notContains":
dbValue = " not like ";
break;
case "more_equal":
dbValue=" >= ";
break;
case "less_equal":
dbValue=" <= ";
break;
default:
break;
}
CurrentOperator = new Operator(cbOperator.Value.ToString() ,cbOperator.Text,dbValue,false);
}
/// <summary>
/// 增加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnAdd_Click(object sender, EventArgs e)
{
CreateCondition(" and ");
}
/// <summary>
/// 或
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnOr_Click(object sender, EventArgs e)
{
CreateCondition(" or ");
}
/// <summary>
/// 取消
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCancel_Click(object sender, EventArgs e)
{
cbValue.SelectedIndex = -1;
cbField.SelectedIndex = 0;
txtValue.Text = "";
cbOperator.SelectedIndex = -1;
CurrentCdtEntity = null;
CurrentOperator = null;
}
/// <summary>
/// 清除所有条件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnClear_Click(object sender, EventArgs e)
{
StrWhereList.Clear();
JoinCondition(); //绑定到显示控件
BindRepeater();
} /// <summary>
/// 删除单个条件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnDelete_Click(object sender, EventArgs e)
{
int index = int.Parse((sender as ASPxButton).CommandArgument);
StrWhereList.RemoveAt(index);
List<CdtEntity> tmpList = StrWhereList.ToList();
for (int i = 0; i < StrWhereList.Count; i++)
{
tmpList[i].Index = i;
}
StrWhereList = tmpList;
JoinCondition();
//绑定到显示控件
BindRepeater();
}
#endregion #region 方法
private string ValidateInput()
{
string errorMsg = "";
if (cbField.Value == null || cbField.Value.ToString() == "")
{
errorMsg += "字段不能为空\r\n";
}
if (cbOperator.Value == null || cbOperator.Value.ToString() == "")
{
errorMsg += "比较符不能为空\r\n";
}
if (CurrentCdtEntity != null)
{
switch (CurrentCdtEntity.DataType)
{
case "formNo":
if (txtValue.Text == "")
{
errorMsg += "条件不能为空\r\n";
}
break;
case "string":
if (txtValue.Text == "")
{
errorMsg += "条件不能为空\r\n";
}
break;
case "date":
if (dtValue.Date == null || dtValue.Date.ToString() == "0001/1/1 0:00:00")
{
errorMsg += "条件不能为空\r\n";
}
break;
case "select":
if (cbValue.Value.ToString() == "")
{
errorMsg += "条件不能为空\r\n";
}
break;
default:
break;
}
} return errorMsg;
}
/// <summary>
/// 初始化操作符
/// </summary>
private void InitOperators()
{
Dictionary<string, List<Operator>> dic = new Dictionary<string, List<Operator>>();
XmlDocument doc = new XmlDocument();
doc.Load(ConfigPath);
Operator entity;
List<Operator> kvList = null;
XmlNodeList xmlNodeList = doc.SelectNodes("/configuration/operators");
foreach (XmlNode xmlNode in xmlNodeList)
{
string dataType = xmlNode.Attributes["dataType"].Value;
if (xmlNode.HasChildNodes)
{
kvList = new List<Operator>();
foreach (XmlNode xmlNode2 in xmlNode.ChildNodes)
{
entity = new Operator(xmlNode2.Attributes["value"].Value, xmlNode2.Attributes["text"].Value, xmlNode2.Attributes["dbValue"].Value, Convert.ToBoolean(xmlNode2.Attributes["selected"].Value));
kvList.Add(entity);
}
}
dic.Add(dataType, kvList);
}
Operators = dic;
}
/// <summary>
/// 初始化数据,在页面里调用
/// </summary>
public void InitData()
{
if (ConfigPath == null)
{
throw new Exception("未指定配置文件路径");
} InitOperators(); CdtEntityList = new List<CdtEntity>();
object value = null;
ListEditItem item = null;
CdtEntity entity = null;
List<Operator> operatorList = null;
XmlDocument doc = new XmlDocument();
doc.Load(ConfigPath);
XmlNode xmlNode = doc.SelectSingleNode("/configuration/fields");
string dataType = "";
foreach (XmlNode node in xmlNode.ChildNodes)
{
dataType = node.Attributes["dataType"].Value;
if (dataType != "")
{
operatorList = Operators[dataType];
if (node.HasChildNodes && node.FirstChild.Name == "items" && node.FirstChild.HasChildNodes)
{
List<Item> itemList = new List<Item>();//select数据类型的数据集合
Item item2 = null;
foreach (XmlNode node2 in node.FirstChild.ChildNodes)
{
item2 = new Item() { Value = node2.Attributes["value"].Value, Text = node2.Attributes["text"].Value };
itemList.Add(item2);
}
value = itemList;
}
entity = new CdtEntity(node.Attributes["name"].Value, node.Attributes["caption"].Value, dataType, int.Parse(node.Attributes["groupSeq"].Value), operatorList, value);
CdtEntityList.Add(entity);
}
item = new ListEditItem(node.Attributes["caption"].Value, node.Attributes["name"].Value);
this.cbField.Items.Add(item);
}
cbField.SelectedIndex = 0;
}
/// <summary>
/// 生成条件
/// </summary>
/// <param name="relation"></param>
private void CreateCondition(string relation)
{
string errorMsg = ValidateInput();
if (errorMsg != "")
{
ScriptManager.RegisterStartupScript(this.UpdatePanel1, GetType(), Guid.NewGuid().ToString(), "alert('" + errorMsg + "')", true);
return;
}
if (StrWhereList == null)
{
StrWhereList = new List<CdtEntity>();
}
CdtEntity entity = null;
switch (CurrentCdtEntity.DataType)
{
case "formNo":
case "string":
case "number":
entity = new CdtEntity(StrWhereList.Count, CurrentCdtEntity.Field, CurrentCdtEntity.Caption, CurrentCdtEntity.DataType,CurrentCdtEntity.GroupSeq, CurrentOperator, txtValue.Text, relation);
break;
case "date":
entity = new CdtEntity(StrWhereList.Count, CurrentCdtEntity.Field, CurrentCdtEntity.Caption, CurrentCdtEntity.DataType, CurrentCdtEntity.GroupSeq, CurrentOperator, dtValue.Date.ToString("yyyy-MM-dd"), relation);
break;
case "select":
entity = new CdtEntity(StrWhereList.Count, CurrentCdtEntity.Field, CurrentCdtEntity.Caption, CurrentCdtEntity.DataType, CurrentCdtEntity.GroupSeq, CurrentOperator, new Item() { Value = cbValue.Value.ToString(), Text = cbValue.Text }, relation);
break;
default:
break;
}
StrWhereList.Add(entity);
JoinCondition();
//绑定到显示控件
BindRepeater();
}
/// <summary>
/// 绑定条件到控件
/// </summary>
private void BindRepeater()
{
List<CdtEntity> ShowList = new List<CdtEntity>();
CdtEntity cModel = null;
foreach (CdtEntity item in StrWhereList)
{
cModel = item.Copy(item);
ShowList.Add(cModel);
}
foreach (CdtEntity item in ShowList)
{
if (item.DataType == "select")
{
item.Value = ((Item)item.Value).Text;
}
}
this.rpConditionList.DataSource = ShowList;
this.rpConditionList.DataBind();
}
/// <summary>
/// 生成sql字符串
/// </summary>
private void JoinCondition()
{
StringBuilder sb = new StringBuilder();
int index = 0;
foreach (CdtEntity item in StrWhereList)
{
//第一个条件
if (index == 0)
{
//如果有包含关系
if (item.Operator.Value == "contains" || item.Operator.Value == "notContains")
{
if (item.DataType == "select")
{
sb.AppendFormat("[{0}:" + item.Field + " " + item.Operator.DbValue + " {1} ]", item.GroupSeq, "''%" + ((Item)item.Value).Value + "%''");
}
else
{
sb.AppendFormat("[{0}:" + item.Field + " " + item.Operator.DbValue + " {1} ]", item.GroupSeq, "''%" + item.Value.ToString() + "%''");
}
}
else//除“包含”相关的以外关系
{
//值为下拉类型
if (item.DataType == "select")
{
//字段为空的情况
if (item.Field.Contains("NULL"))
{
sb.AppendFormat("[{0}:{1} ]", item.GroupSeq, ((Item)item.Value).Value);
}
else
{
sb.AppendFormat("[{0}:" + item.Field + " " + item.Operator.DbValue + " " + "''" + ((Item)item.Value).Value + "''" + " ]", item.GroupSeq);
}
}
else
{
sb.AppendFormat("[{0}:" + item.Field + " " + item.Operator.DbValue + " " + "''" + item.Value.ToString() + "''" + " ]", item.GroupSeq);
}
}
}
else
{
if (item.Operator.Value == "contains" || item.Operator.Value == "notContains")
{
if (item.DataType == "select")
{
sb.AppendFormat(item.Relation + "[{0}:" + " " + item.Field + " " + item.Operator.DbValue + " {1} ]", item.GroupSeq, "''%" + ((Item)item.Value).Value + "%''");
}
else
{
sb.AppendFormat(item.Relation + "[{0}:" + " " + item.Field + " " + item.Operator.DbValue + " {1} ]", item.GroupSeq, "''%" + item.Value.ToString() + "%''");
}
}
else
{
//值为下拉类型
if (item.DataType == "select")
{
if (item.Field.Contains("NULL"))
{
sb.AppendFormat(item.Relation + "[{0}:{1} ]", item.GroupSeq, ((Item)item.Value).Value);
}
else
{
sb.AppendFormat(item.Relation + "[{0}:" + " " + item.Field + " " + item.Operator.DbValue + " " + "''" + ((Item)item.Value).Value + "''" + " ]", item.GroupSeq);
}
}
else
{
sb.AppendFormat(item.Relation + "[{0}:" + " " + item.Field + " " + item.Operator.DbValue + " " + "''" + item.Value.ToString() + "''" + " ]", item.GroupSeq);
}
}
}
index++;
}
StrWhere = sb.ToString();
} #endregion
}

以上控件的代码都有了,页面调用就简单多了

使用

aspx:

<cdt:Condition ID="Condition1" runat="server" />

初始化配置文件:

Condition1.ConfigPath = AppDomain.CurrentDomain.BaseDirectory + "\\DetectSelect\\Cost.config";
Condition1.InitData();

获取查询条件:

string where = Condition1.StrWhere;

这里得到的条件类似[1:Operate_Time >= ''2013-6-1''] and [1:Send_CustName like '%北京XX有限公司%']

这里是由于我业务上的特殊需要,后台数据实在是太复杂了,不能用一张表或者一个视图来查询数据,条件字段不能从一张表里去取,所以分组查询逐级获取主表主键字段的值存放到临时表再去获取数据。

如果是一般的查询,只要不是很复杂的,业务逻辑可以稍微改的简单一些,这里字符串的拼接操作可不少哦,别看晕了,事实上还是蛮简单的。

效果预览

写完收工。

 
 
分类: Asp.net

asp.net通用查询模块设计的更多相关文章

  1. ABP模块设计

    ABP模块设计 返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术 ...

  2. 解析大型.NET ERP系统 权限模块设计与实现

    权限模块是ERP系统的核心模块之一,完善的权限控制机制给系统增色不少.总结我接触过的权限模块,以享读者. 1 权限的简明定义 ERP权限管理用一句简单的话来说就是:谁 能否 做 那些 事. 文句 含义 ...

  3. ASP.NET Core模块概述

    原文地址:ASP.NET Core Module overview By Tom Dykstra, Rick Strahl, and Chris Ross ASP.NET Core模块(ANCM)让你 ...

  4. .NET 缓存模块设计

    上一篇谈了我对缓存的概念,框架上的理解和看法,这篇承接上篇讲讲我自己的缓存模块设计实践. 基本的缓存模块设计 最基础的缓存模块一定有一个统一的CacheHelper,如下: public interf ...

  5. IOS编程 图片缓存模块设计

    手机客户端为什么会留存下来?而不是被一味的Wap替代掉?因为手机客户端有Wap无可替代的优势,就是自身较强的计算能力. 手机中不可避免的一环:图片缓存,在软件的整个运行过程中显得尤为重要. 先简单说一 ...

  6. ylbtech-Model-Account(通用账户模块设计)

    ylbtech-DatabaseDesgin:ylbtech-Model-Account(通用账户模块设计) ylbtech-Model-Account(通用账户模块设计) 1.A,数据库关系图(Da ...

  7. thinkphp 5.0 模块设计

    模块设计 5.0版本对模块的功能做了灵活设计,默认采用多模块的架构,并且支持单一模块设计,所有模块的命名空间均以app作为根命名空间(可配置更改). 目录结构 标准的应用和模块目录结构如下: ├─ap ...

  8. Java开源生鲜电商平台-通知模块设计与架构(源码可下载)

    Java开源生鲜电商平台-通知模块设计与架构(源码可下载) 说明:对于一个生鲜的B2B平台而言,通知对于我们实际的运营而言来讲分为三种方式:           1. 消息推送:(采用极光推送)   ...

  9. Java开源生鲜电商平台-团购模块设计与架构(源码可下载)

    Java开源生鲜电商平台-团购模块设计与架构(源码可下载) 说明:任何一个电商系统中,对于促销这块是必不可少的,毕竟这块是最吸引用户的,用户也是最爱的模块之一,理由很简单,便宜. 我的经验是无论是大的 ...

随机推荐

  1. Java清理临时目录文件Demo(一)

    /** * 删除单个文件 * * @param sPath * 被删除文件的文件名 * @return 单个文件删除成功返回true,否则返回false */ public static boolea ...

  2. Appium Android Bootstrap源码分析之命令解析执行

    通过上一篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>我们知道了Appium从pc端发送过来的命令如果是控件相关的话,最终目标控件在b ...

  3. [android] 百度地图开发 (两).所在地的城市定位和城市POI搜索

    一个. 百度地图城市位置和POI搜索知识       上一篇文章"百度地图开发(一)"中讲述了怎样申请百度APIKey及解决显示空白网格的问题.该篇文章主要讲述怎样定位城市位置.定 ...

  4. 分享12款经典时尚的HTML5应用

    分享伟大,呵呵.今天给大家分享一下收集的12个HTML5小特效. 我整理一下源码,给大家打包一下,我博客园上传文件大小有限,传不了了. 需要的请留下邮箱就行了,觉得好的话,不要忘了点赞哦~ 1.CSS ...

  5. VMWare 11安装操作系统 - 初学者系列 - 学习者系列文章

    在2010年的时候,我写过一篇关于VMWare的安装操作系统的博文.但是今天在QQ群里有人问起VMWare安装操作系统的问题,虽然回答了,但是回头看了下当时那篇博文,决定重新写一文. 首先要获取VMW ...

  6. 【C#版本详情回顾】C#4.0主要功能列表

    诊断和性能 从 .NET Framework 4 开始,您可以获得每个应用程序域的处理器使用情况和内存使用情况估计值 通过托管承载 API.本机承载 API 以及 Windows 事件跟踪 (ETW) ...

  7. ASP.NET MVC5 视图预编译

    ASP.NET MVC5 视图预编译 ASP.NET MVC5 视图预编译   关于Razor视图及引擎原理,就不多说了. 这里通俗或者不恰当地说,cshtml视图文件是先编译成dll文件,再通过视图 ...

  8. HBase MVCC 代码阅读(一)

    MultiVersionConcurrencyControl.java,版本 0.94.1 MultiVersionConsistencyControl 管理 memstore 中的读写一致性.该类实 ...

  9. 迁移Model元数据设置项

    .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序) 阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1 ...

  10. Unity Container

    Unity Container中的几种注册方式与示例 2013-12-08 22:43 by 小白哥哥, 22 阅读, 0 评论, 收藏, 编辑 1.实例注册 最简单的注册方式就是实例注册,Unity ...