码迷,mamicode.com
首页 > Windows程序 > 详细

WinForm动态查询

时间:2017-12-22 18:29:16      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:span   void   名称   src   属性绑定   inter   文本框   control   查询条件   

WinForm 动态查询

1. 使用场景

在对数据进行筛选, 包含多个筛选字段时适用.

技术分享图片

2. 接口设计

    /// <summary>
    /// 定义可作为追加到 WHERE 子句的控件接口
    /// </summary>
    internal interface IWhereSentence
    {
        /// <summary>
        /// 当前控件名称
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 对应数据表中的字段名称
        /// </summary>
        string FieldName { get; set; }

        /// <summary>
        /// 操作符
        /// </summary>
        string Operator { get; set; }

        /// <summary>
        /// 是否作为查询条件
        /// </summary>
        bool AsQuery { get; set; }
    }

    /// <summary>
    /// 定义可追加到 WHERE 子句的控件泛型接口
    /// </summary>
    /// <typeparam name="T">值的类型</typeparam>
    internal interface IWhereSentence<T> : IWhereSentence
    {
        /// <summary>
        /// 实际值
        /// </summary>
        T Value { get; set; }
    }

3. 接口实现, 以常见的 DateTimePickerTextox 控件举例

  • 自定义控件, 继承框架提供的 DateTimePicker 类和 IWhereSentence<DateTime> 接口:

    /// <summary>
    /// 可追加到查询条件的日期选择器
    /// </summary>
    public partial class QueryDataTimerPicker : DateTimePicker, IWhereSentence<DateTime>
    {
        public QueryDataTimerPicker() : base() { }
    
        /// <summary>
        /// 是否作为查询条件
        /// </summary>
        [DisplayName("是否作为查询条件")]
        public bool AsQuery { get; set; }
    
        /// <summary>
        /// 字段名
        /// </summary>
        [DisplayName("字段名称")]
        public string FieldName { get; set; }
    
        /// <summary>
        /// 操作符
        /// </summary>
        [DisplayName("操作符")]
        public string Operator { get; set; }
    }
  • 自定义控件,继承框架提供的 TextBox 控件和 IWhereSentence<string> 接口. AsQuery属性可根据文本框是否有值, 返回是否作为查询条件, Value 属性与文本框自身的 Text 属性绑定

    /// <summary>
    /// 可追加到查询条件的文本框
    /// </summary>
    public class QueryTextBox : TextBox, IWhereSentence<string>
    {
        private bool _asQuery;
        public QueryTextBox() : base() { }
    
        /// <summary>
        /// 是否作为查询条件
        /// </summary>
        [DisplayName("是否作为查询条件")]
        public bool AsQuery
        {
            get { return this._asQuery && !string.IsNullOrWhiteSpace(this.Text); }
            set { this._asQuery = value; }
        }
    
        /// <summary>
        /// 字段名
        /// </summary>
        [DisplayName("字段名称")]
        public string FieldName { get; set; }
    
        /// <summary>
        /// 操作符
        /// </summary>
        [DisplayName("操作符")]
        public string Operator { get; set; }
    
        /// <summary>
        /// 实际值
        /// </summary>
        public string Value { get { return this.Text; } set { this.Text = value; } }
    }

4. 运用

将自定义控件放置在目标窗体上, 可在属性窗口设置相关属性:

技术分享图片
技术分享图片

  • 定义查询控件集合

    private IWhereSentence[] _queryControls;
    this._queryControls = new IWhereSentence[]
    {
        this.queryDataTimerPickerStart,
        this.queryDataTimerPickerEnd,
        this.queryTextBoxTemp
    };
  • 获取WHERE子句

        /// <summary>
        /// 根据查询条件生成WHERE字符串, 用于SQL查询
        /// </summary>
        /// <returns>包含WHERE的SQL字符串</returns>
        private string GetWhereString()
        {
            var builderInst = PooledStringBuilder.GetInstance();
            var builder = builderInst.Builder;
            builder.Append("WHERE ");
    
            using (var enumerator = this._queryControls.Where(p => p.AsQuery).GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    builder.Clear();
                    return builderInst.ToStringAndFree();
                }
                AppendWhere(builder, enumerator.Current);
    
                while (enumerator.MoveNext())
                {
                    builder.Append(" AND ");
                    AppendWhere(builder, enumerator.Current);
                }
            }
            return builderInst.ToStringAndFree();
        }
    
        /// <summary>
        /// 将当前查询控件追加到WHERE字符串中
        /// </summary>
        /// <param name="builder"><see cref="StringBuilder"/>对象</param>
        /// <param name="item">当前查询控件</param>
        private void AppendWhere(StringBuilder builder, IWhereSentence item)
        {
            builder.Append(item.FieldName);
            if (_formatRegex.IsMatch(item.Operator))
                builder.Append(" ").AppendFormat(item.Operator, $"‘ + @{item.Name} + ‘");
            else
                builder.Append(" ").Append(item.Operator).Append(" ").Append("@").Append(item.Name);
        }
    
        /// <summary>
        /// 获取查询参数实际值
        /// </summary>
        /// <returns>查询参数组成的匿名对象</returns>
        private object GetQueryParam()
        {
            return new
            {
                queryDataTimerPickerStart = this.queryDataTimerPickerStart.Value,
                queryDataTimerPickerEnd = this.queryDataTimerPickerEnd.Value,
                queryTextBoxTemp = this.queryTextBoxTemp.Value
            };
        }
  • 查询

    var sql = "...";
    sql = sql + GetWhereString();
    var param = GetQueryParam();
    var result = conn.Query(sql, param);    //使用Dapper

5. 问题

  • 当前接口的定义了操作符属性, 在拼接SQL时, 未实现面对复杂运算符的情况, 目前支持 LIKE(‘{0}‘)运算符.
  • 多个条件之间默认使用 AND 连接, 若要扩展到使用 OR 或者其他运算符, 可在IWhereSentence接口中添加属性
  • 针对SQL Server数据库, 若要针对MySQL或Oracle等其他数据库, 需更改SQL参数标识符 @.

WinForm动态查询

标签:span   void   名称   src   属性绑定   inter   文本框   control   查询条件   

原文地址:http://www.cnblogs.com/aning2015/p/8087006.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!