MS大家不喜欢我说思路的方式,今天一鼓作气,把剩下的关键代码,类图贴完,加上简单说明,本系列到此结束。

我觉得技术网站应当以交流思想为主,现在看来,大家比较关注代码,呵。

界面上不写了,都比较弱智,而且我是CS的。

1.       布尔表达式的处理。

前面说过,布尔表达式两种形式

Exp àCol   + compareOp + Value

Exp àExp + boolOP +Exp

先定义compareOp和boolOp

这里没有用枚举而用静态单例,原因还是老调子,因为要有Show 和EXP

CompareOP

 

67 

BoolOp

 

 SFTech.Query.Entity
{
    public class  BoolOp
    {

        
private string _Show;
        
private string _Exp;
        
private int _Value;
        
private BoolOp(String show, string exp, int value) { _Show = show; _Exp = exp; _Value = value; }
 
        
public String Show{get{return _Show ;}}
        
public override string ToString()
        {
            
            
return _Exp.ToString();
        }


        
public string Exp
        {
            
get
            {
                
return _Exp;
            }
        }

        
/// <summary>
        
/// 并且
        
/// </summary>

        
public static readonly  BoolOp And = new BoolOp("并且"," and ",0);
        
/// <summary>
        
/// 或者
        
/// </summary>
        public static readonly  BoolOp OR = new BoolOp("或者"" or "1);
    }
}

 

下面讨论布尔表达式的生成方式 。

一种是Exp àCol   + compareOp + Value

所以直观上类中应该有一个QueryCol,一个comareOP,和一个value做为布表达式的成员。

而对于value ,当然,我们还要分show和Exp

而对于第二种生成方式。

Exp àExp + boolOP +Exp

还是用“妥协的设计方式”,加一个不论不类的类AddBoolOp,有BoolOp和BoolExpresion两个成员。

这样BoolExpression再加一个List<AddBoolOp>就可以了。

对于在两种方式切换,我们加一个IsFirst的属性、

具体内容不多说,写代码里(大家要的就是这个吧,不好意思,两天了,我还是窝不住火,说话冲点,各位大爷息怒)、

对了,生成条件表达式的内容加在ToString()中了,这个招确实有点下三滥,呵呵,不好意思啦。

 

 SFTech.Query.Entity
{
    /// <summary>
    
/// 表示一个布尔表达式
    
/// </summary>
    public class BoolExpression
    {



        
public BoolExpression(QueryCol col, CompareOp op, String value, String show)
        {
            
this.DataCol = col;
            
this.CompareOp = op;
            
this.Value = value;
            
this.ShowValue = show;
            
this.Sequences = new ExpressionSequences();
            IsSingle 
= true;

        }


        
 
        
private ExpressionSequences _sequences;
        
public ExpressionSequences Sequences
        {
            
get
            {
                
return _sequences;
            }
            
private set
            {
                _sequences 
= value;

            }
        }

        
private QueryCol _DataCol;
        
public QueryCol DataCol
        {
            
get
            {
                
return _DataCol;
            }
            
set
            {
                _DataCol 
= value;
            }
        }

        
private string _Value;
        
public String Value
        {
            
get
            {
                
return _Value;
            }
            
set
            {
                _Value 
= value;
            }
        }

        
private CompareOp _CompareOp;
        
public CompareOp CompareOp
        {
            
get
            {
                
return _CompareOp;
            }
            
private set
            {
                _CompareOp 
= value;
            }
        }
        
private string _ShowValue;
        
public string ShowValue
        {
            
get
            {
                
return _ShowValue;
            }
            
set
            {
                _ShowValue 
= value;
            }
        }

        
public override string ToString()
        {
           

            
            
string result;
            
if (IsSingle)
                result 
=  " ("+this.DataCol.DataTable.Exp +"."+ this.DataCol.Exp +" "+ this.CompareOp.Exp + " '" + this.Value + "') ";
            
else
                result 
= First.ToString();

            
foreach (var q in this.Sequences)
            {
                result 
= result + q.BoolOp.Exp   + q.BoolExpression.ToString();
            }
            
if(this.Sequences .Count > 0)
            result 
= " ("+result +"";
            
return result;
        }


        
private bool _IsSigle;
        
public bool IsSingle
        {
            
get
            {
                
return _IsSigle;
            }
            
set
            {
                
                _IsSigle 
= value;
                
if (_IsSigle == false)
                {
                    
this.First = new BoolExpression(this.DataCol, this.CompareOp, this.Value, this.ShowValue);
                }
            }
        }



        
private BoolExpression _First;
        
public BoolExpression First
        {
            
get
            {
                
return _First;
            }
            
private set
            {
                _First 
= value;
            }
        }
    }
}

妥协类AddBoolExpression和其集合。

 

 SFTech.Query.Entity
{
    public class AddBoolExpression
    {

        
public AddBoolExpression(BoolOp op, BoolExpression exp)
        {
            BoolOp 
= op;
            BoolExpression 
= exp;
        }

        
private BoolOp _BoolOp;
        
public BoolOp BoolOp
        {
            
get
            {
                
return _BoolOp;
            }
            
set
            {
                _BoolOp 
= value;
            }
        }

        
private BoolExpression _Exp;
        
public BoolExpression BoolExpression
        {
            
get
            {
                
return _Exp;// throw new System.NotImplementedException();
            }
            
set
            {
                _Exp 
= value;
            }
        }
    }
}

 

 SFTech.Query.Entity
{
    public class ExpressionSequences  : List<AddBoolExpression>
    {
    }
}

 

现在还剩对选择列的处理。

前面说了select后面的列,可以是group 的列,也可以是count,sum,也可以是是值,因此先定义输出的方式 ,还是静态类(这招快让我用吐了,呵呵)

 

 SFTech.Query.Entity
{
    public class SelectType
    {
        
private string show;
        
public string Show{
            
get{
                
return show;
            }
            
private set {
                show 
= value;
            }
        }
        
private string dbexp;
        
public string DBExp{
            
get{
                
return dbexp ;
            }
            
private set {
                dbexp 
= value;
            }
        }
        
private SelectType (string _Show,string _exp){
            Show 
= _Show;
            DBExp 
= _exp;
        }


        
public static readonly SelectType Value = new SelectType("""");
        
public static readonly SelectType MAX = new SelectType("最大""MAX");
        
public static readonly SelectType MIN = new SelectType("最小""MIN");
        
public static readonly SelectType COUNT = new SelectType("数量""COUNT");
        
public static readonly SelectType SUM = new SelectType("求和""SUM");
        
public static readonly SelectType AVG = new SelectType("平均值""AVG");
        
public static List<SelectType> Types
        {
            
get
            {
                List
<SelectType> item = new List<SelectType>();
                
                item.Add(MAX);
                item.Add(MIN);
                item.Add(SUM);
                item.Add(COUNT);
                item.Add(AVG);
                
return item;
            }
        }
         
    }
}

下面就是选择的列了、

 

 SFTech.Query.Entity
{
    /// <summary>
    
/// 表示选择的要输出的或分组的列
    
/// </summary>
    public class SelectedCol
    {


        
private bool _IsGroup;
        
/// <summary>
        
/// 是否分组
        
/// </summary>
        public bool IsGroup
        {
            
get
            {
                
return _IsGroup;
            }
            
set
            {
                _IsGroup 
= value;
            }
        }

        
private bool _isPrint;
        
public bool IsPrint
        {
            
get
            {
                
return _isPrint;
            }
            
set
            {
                _isPrint 
= value;
            }
        }


        
private int _SelectedIndex;
        
/// <summary>
        
/// 选择/分组顺序
        
/// </summary>
        public int SelectedIndex
        {
            
get
            {
                
return _SelectedIndex;
            }
            
set
            {
                _SelectedIndex 
= value;
            }
        }



        
private QueryCol _DataCol;
        
public QueryCol DataCol
        {
            
get
            {
                
return _DataCol;
            }
            
set
            {
                _DataCol 
= value;
            }
        }

        
private SelectType _Type;
        
public SelectType SelectType
        {
            
get
            {
                
return _Type;
            }
            
set
            {
                _Type 
= value;
            }
        }


        
public SelectedCol(QueryCol Col, SelectType Type)
        {
            
this.DataCol = Col;
            
this.SelectType = Type;
        }
    }
}

在定义一个选择列的集合,对一些条件,约束的判断加在这里了

 

 SFTech.Query.Entity
{
    public class SelectedColCollection : IList<SelectedCol >,ICollection<SelectedCol>
    {

        
private Query.Entity.QueryContext _context;

        
public Query.Entity.QueryContext Context
        {
            
get
            {
                
return _context;
            }
            
set
            {
                _context 
= value;
            }
        }

        
private List<SelectedCol> _items;
        
private int GroupCount
        {
            
get
            {
                
return (from cols in this
                        
where cols.IsGroup == true
                        select cols).Count();
            }
        }
        
public SelectedColCollection()
        {
            _items 
= new List<SelectedCol>();
        }
        
#region IList<SelectedCol> 成员

        
public int IndexOf(SelectedCol item)
        {
            
return _items.IndexOf(item);
        }

        
public void Insert(int index, SelectedCol item)
        {
            _items.Insert (index, item);
        }

        
public void RemoveAt(int index)
        {
            _items.RemoveAt(index);
        }

        
public SelectedCol this[int index]
        {
            
get
            {
                
return _items[index];
            }
            
set
            {
                
throw new NotImplementedException();
            }
        }

        
#endregion

        
#region ICollection<SelectedCol> 成员

        
public void Add(SelectedCol item)
        {

            
            
if (this.IndexOf(item) > 0)
                
throw new Exception("要添加的列已经存在!");
            
if (this.GroupCount > 0
                
&& item.IsGroup == false
                
&& item.SelectType == SelectType.Value)
            {
                
throw new Exception("查询中已经包含了分组值,不能再添加非分组的求值。");
            }

            
if(item.IsGroup == false && item.SelectType != SelectType.Value 
                
&&( from se in this._items where se.SelectType == SelectType.Value && se.IsGroup ==false  select se).Count ()>0)
                
throw new Exception ("已经有其他的输出值,不能再添加非值的统计值");
 

            
if (item.IsGroup == true)
            {
                var q 
= from s in _items
                        
where s.SelectType == SelectType.Value
                        select s;
                
int i = 0;
                
while(_items .Count > 0 &&i<_items.Count ){

                    var r 
= _items[i];
                    
if (r.SelectType == SelectType.Value && r.IsGroup == false)
                    {
                        _items.Remove(r);
                        
this.Context.ColCollection.Add(r.DataCol );
                    }
                    
else i++;
                }
            }

            
            _items.Add(item);
            
if(item.SelectType == SelectType.Value )
            
this.Context.ColCollection.Remove(item.DataCol);
            
for (int i = 0; i < _items.Count; i++)
                _items[i].SelectedIndex 
= i;

        }

        
public void Clear()
        {
            _items.Clear();
        }

        
public bool Contains(SelectedCol item)
        {
            
return _items.Contains(item);
        }

        
public void CopyTo(SelectedCol[] array, int arrayIndex)
        {
            _items.CopyTo (array, arrayIndex);
        }

        
public int Count
        {
            
get { return _items.Count; }
        }

        
public bool IsReadOnly
        {
            
get { return true; }
        }

        
public bool Remove(SelectedCol item)
        {
            
return _items.Remove(item);
        }

        
#endregion

        
#region IEnumerable<SelectedCol> 成员

        
public IEnumerator<SelectedCol> GetEnumerator()
        {
            
return _items.GetEnumerator();
        }

        
#endregion

        
#region IEnumerable 成员

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            
return _items.GetEnumerator();
        }

        
#endregion

       
    }
}

 

最后是一个生成查询的类QueryContext。

 

 SFTech.Query.Entity
{
    public class QueryContext
    {
        
private JoinConditions _conditions;
        
private TableCollection AllTables;


        
private TableCollection _SelectedTables;
        
public  TableCollection SelectedTables
        {
            
get
            {
                
return _SelectedTables;
            }
            
set
            {
                _SelectedTables 
= value;
            }
        }


        
private TableCollection _CanSelectTable;
        
public TableCollection CanSelelctTables
        {
            
get
            {
                
return _CanSelectTable;
            }
            
set
            {
                _CanSelectTable 
= value;
            }
        }

        
private ColCollection _ColCollection;
        
public ColCollection ColCollection
        {
            
get
            {
                
return _ColCollection;
            }
            
set
            {
                _ColCollection 
= value;
            }
        }
        
public QueryContext()
        {
            
this.SelectedColCollection = new SelectedColCollection();
            
this.SelectedTables = new TableCollection();
            
this.CanSelelctTables = new TableCollection();
            
this._conditions = new JoinConditions();
            
this.ColCollection = new ColCollection();
            
this.SelectedColCollection.Context = this;
            AllTables 
= new TableCollection();
            
using (DBDataContext context = Global.Context )
            {
                var tablecols 
= from table in context.SE_Table
                                from col 
in context.SE_Col
                                
where col.ColTable == table.Exp
                                group 
new { Table = table, Col = col } by table;
                
foreach (var t in tablecols)
                {
                    QueryTable table 
= new QueryTable(t.Key.Exp, t.Key.Show);
                    
foreach (var c in t)
                    {
                        table.Cols.Add(
new QueryCol(c.Col.ColExp, c.Col.ColShow, table, (int)c.Col.ColType, c.Col.ColStateString));
                    }
                    AllTables.Add(table);
                    CanSelelctTables.Add(table);
                }
                var joins 
= from j in context.SE_Join 
                            select j;
                
foreach(var join in joins){
                    _conditions.Add(
new JoinCondition(AllTables[join.Parent].Cols[join.ParentCol], AllTables[join.Child].Cols[join.ChildCol]));
                }
            }

        }
        
public void Add(QueryTable Table)
        {
            
if (this.SelectedTables.Count != 0)
            {

                var q 
= from joins in this._conditions
                        from tables 
in this.SelectedTables
                        
where (joins.LeftCol.DataTable.Exp == Table.Exp
                        
&& joins.RightCol.DataTable.Exp == tables.Exp)
                        
|| (joins.RightCol.DataTable.Exp == Table.Exp
                        
&& joins.LeftCol.DataTable.Exp == tables.Exp)
                        select joins;
                
if (q.Count() == 0)
                {
                    
throw new Exception("无法将" + Table.Show + "添加到现有查询,找不到可以关联的信息。");
                }
            }
            
this.SelectedTables.Add(Table);
            
this.ColCollection.AddRange(Table.Cols);

            
this.CanSelelctTables.Clear();
            var canselect 
= from all in this.AllTables
                            from canjoin 
in this._conditions
                            from selected 
in this.SelectedTables
                            
where (all.Exp == canjoin.LeftCol.DataTable.Exp
                            
&& selected.Exp == canjoin.RightCol.DataTable.Exp)
                            
|| (all.Exp == canjoin.RightCol.DataTable.Exp
                            
&& selected.Exp == canjoin.LeftCol.DataTable.Exp)
                            select all;
            
foreach (var canjontable in canselect)
            {
                
if (this.SelectedTables.Contains(canjontable) == false)
                {
                    
this.CanSelelctTables.Add(canjontable);
                }
            }

        }

        
public void Clear()
        {
            
this.SelectedTables.Clear();
            
this.SelectedColCollection.Clear();
            
this.ColCollection.Clear();
            
this.CanSelelctTables.Clear();
            
foreach (QueryTable table in AllTables)
            {
                
this.CanSelelctTables.Add(table);
            }
            
this.BoolExpression = null;
            
        }


        
private SelectedColCollection _SelectdCoCollection;
        
public SelectedColCollection SelectedColCollection
        {
            
get
            {
                
return _SelectdCoCollection;
            }
            
private set
            {
                _SelectdCoCollection 
= value;
            }
        }



        
private BoolExpression _BoolExp;
        
public BoolExpression BoolExpression
        {
            
get
            {
                
return _BoolExp;
            }
            
set
            {
                _BoolExp 
= value;
            }
        }

        
/// <summary>
        
/// 将查询保存在数据库中
        
/// </summary>
        public void Save()
        {
            
throw new System.NotImplementedException();
        }

    

        
public  String GetSql()
        {

            
string groupstr="";
            
string selectedstr="";
            
string tablestr="";
            
string exp = "";

            
#region 得到选择的表


            
if(this.SelectedTables.Count == 0)
                
throw new Exception ("无法查生成查询:没有选择表");
            TableCollection addTables 
= new TableCollection();
            
foreach (QueryTable table in this.SelectedTables)
            {

                
if (addTables.Count == 0)
                {
                    tablestr 
= " FROM " + table.Exp;
                    
                }
                
else
                {
                    var q 
= from addedtable in addTables
                            from joins 
in _conditions
                            
where (addedtable.Exp == joins.LeftCol.DataTable.Exp
                            
&& table.Exp == joins.RightCol.DataTable .Exp)
                            
|| (addedtable.Exp == joins.RightCol.DataTable.Exp
                            
&& table.Exp == joins.LeftCol.DataTable.Exp)
                            select joins;
                    
if (q.Count() == 0)
                        
throw new Exception("无法形成连接表");
                    
string join = "";
                    
foreach (var j in q)
                    {
                        
if (join != "")
                            join 
= join + " AND ";
                        join 
="["+ j.LeftCol.DataTable.Exp +"].["+j.LeftCol.Exp+ "]=["+j.RightCol .DataTable.Exp +"].["+j.RightCol.Exp +"]";


                    }
                    tablestr 
= tablestr + " JOIN [" + table.Exp + "] ON (" + join + ")";
                }
                addTables.Add(table);
            }

            
#endregion

            
#region 得到选择列和分组列
            var groupCols 
= from cols in this.SelectedColCollection
                            orderby cols.SelectedIndex
                            select cols;

            
if((from col in this.SelectedColCollection 
                
where col.IsPrint == true select col ).Count()==0)
                
throw new Exception("无法生成查询:没有选择要输出的列");

            
if (groupCols.Count() > 0)
            {
                groupstr 
= "";
                selectedstr 
= "SELECT ";
                
foreach (var groucol in groupCols)
                {
                    
if (groucol.IsGroup)
                    {
                        
if(groupstr == "")
                            groupstr 
=" GROUP BY ";
                        groupstr 
+= "[" + groucol.DataCol.DataTable.Exp + "].[" + groucol.DataCol.Exp + "],";
                    }
                    selectedstr 
+=groucol.SelectType.DBExp + "([" + groucol.DataCol.DataTable.Exp + "].[" + groucol.DataCol.Exp + "]) AS [" + groucol.DataCol.Show + groucol.SelectType.Show +"],";
                }
                
if(groupstr != "")
                groupstr 
= groupstr.Substring(0, groupstr.Length - 1);//去掉最后一 个,
               
                selectedstr 
= selectedstr.Substring(0, selectedstr.Length - 1);
            }
            
if(this.BoolExpression != null)
            exp 
=" WHERE "+ this.BoolExpression.ToString();
            
#endregion
 
            
return selectedstr + tablestr + exp + groupstr;




        }
    }
}

其中对多表连查的条件判断已经加到里面了,到此,全部关键代码。算法都已经搞定。

至于界面是BS还是CS 各位自便。

在此贴上几张俺的CS效果图(很草,算demo吧)

 主界面

基于数据字典的查询系统 最后一篇到完工

串查询

 

基于数据字典的查询系统 最后一篇到完工

数值(和串基本相同)

基于数据字典的查询系统 最后一篇到完工

状态位

基于数据字典的查询系统 最后一篇到完工

输出方式

基于数据字典的查询系统 最后一篇到完工

仍然那句,欢迎拍砖(理性,不是急性)

相关文章: