WinForm動態查詢
阿新 • • 發佈:2017-12-22
while esp tex 集合 play server emp 操作 num 3. 接口實現, 以常見的
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. 接口實現, 以常見的 DateTimePicker
和 Textox
控件舉例
自定義控件, 繼承框架提供的
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動態查詢