在C#中处理多参数查询的模式或最佳实践

时间:2010-06-10 19:16:39

标签: c# design-patterns parameters

我在编写winforms或wpf应用程序以对数据库执行查询时总是采用的方法如下:

  • 设计一个包含多个控件的接口,以将参数传递给我的查询类

  • 使用Linq或Entity Framework作为数据源构建包含查询的字段,属性和方法的“DataAccess”类。

  • 管理控件生成的事件,传递参数并选择用于检索数据的方法。

DataAccess类的示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyApplication
{
    public class DataAccess
    {
        public LinqDataContext db = new LinqDataContext();

#region Private Fields
#region Properties(Constructors)
#region Methods

// Sample method
public List<DataAccess> Mymethod(string valoredata, int esenzione,
            string valorebatch)
{
    if (esenzione == 0)
    {
        return (from elementi in db.IndexTables
            from elementi2 in db.DocumentTables
            where elementi.ID == elementi2.ID 
                && elementi.DataScansione == Convert.ToDateTime(valoredata)
                && elementi.Batch == valorebatch  
                && elementi.NonEsente == true                    
            select associazionePropieta(elementi, elementi2)).ToList();
    }
    else if (esenzione == 1) 
    {
        return (from elementi in db.IndexTables
            from elementi2 in db.DocumentTables
            where elementi.ID == elementi2.ID 
                && elementi.DataScansione == Convert.ToDateTime(valoredata)
                && elementi.Batch == valorebatch 
                && elementi.BiffaturaReddito == false 
                && elementi.FirmaAutocertificazione == false 
                && elementi.NonEsente == false
            select associazionePropieta(elementi, elementi2)).ToList();
    }
    else
    {
        return (from elementi in db.IndexTables
            from elementi2 in db.DocumentTables
            where elementi.ID == elementi2.ID 
                && elementi.DataScansione == Convert.ToDateTime(valoredata)
                && elementi.Batch == valorebatch 
                && (elementi.BiffaturaReddito == true 
                    || elementi.FirmaAutocertificazione == true)
            select associazionePropieta(elementi, elementi2)).ToList();
    }

}

#endregion

// From Refactoring...
private static DataAccess associazionePropieta(IndexTable elementi, 
                             DocumentTable elementi2)
{
    return new DataAccess
    {
        codiceImpegnativa = elementi.CodiceImpegnativa,
        nominativo = elementi.Nominativo,
        codiceFiscale = elementi.CodiceFiscale,
        dataImpegnativa = elementi.DataImpegnativa,
        nonEsente = Convert.ToBoolean(elementi.NonEsente),
        biffaturaReddito = Convert.ToBoolean(elementi.BiffaturaReddito),
        autocertificazione = Convert.ToBoolean(elementi.FirmaAutocertificazione),
        codiceEsenzione = elementi.CodiceEsenzione,
        raoU = Convert.ToBoolean(elementi.RaoU),
        raoB = Convert.ToBoolean(elementi.RaoB),
        raoD = Convert.ToBoolean(elementi.RaoD),
        raoP = Convert.ToBoolean(elementi.RaoP),
        dataScansione = Convert.ToDateTime(elementi.DataScansione),
        batch = elementi.Batch,
        documentID = elementi.DcumentID,
        path = elementi2.Path,
        ID = elementi2.ID.ToString()
    };
}

这是“MainWindow”代码中的一小部分,我有7个控件(1个日期选择器,3个组合框和3个文本框)用作查询的参数:

if (datePickerData.SelectedDate != null 
        && comboBatch.SelectedValue == null
        && comboEsenzione.SelectedValue != null 
        && nome == true 
        && impegnativa == true 
        && fiscale == true)
{
    this.dataGridRisultati.ItemsSource =
        dati.Mymethod(datePickerData.SelectedDate.ToString(),
            comboEsenzione.SelectedIndex);
}

}

你有没有想象,处理所有可以传递的参数组合和决策结构(if或switch case)正在成为一项巨大的工作......我在区域中分散了决策方法(1个参数,2个参数, 3 .... 7参数),这给了我一些休息,但今天我只是停在4参数区域,我不知道我是否只是累了什么,但我无法弄清楚一个模式匹配所有组合。

所以最后我的问题是:

我确信有一种更简单的方法来处理用户使用组合框代替文本框的概率,或者同时所有7个控件来查询我的数据库,但我只是无法想象它出来了。

是否有最佳做法或模式可以提供帮助?

提前致谢

2 个答案:

答案 0 :(得分:5)

我不确定我是否100%完全理解您的问题,但我相信您在询问有多种参数时构建数据访问调用的有效方法,但它们是可选的。

您可能不知道可以分阶段构建LINQ查询。例如,想一想:

var query = from record in datasource
    select record;

if (Parameter1HasValue) query = query.Where(record => record.Field1 == Parameter1);
if (Parameter2HasValue) query = query.Where(record => record.Field2 == Parameter2);
if (Parameter3HasValue) query = query.Where(record => record.Field3 == Parameter3);
return query.ToList();

您可能在一个将所有过滤器作为可空参数的方法中使用此方法,或者过滤器值可能是数据访问类的其他属性 - 这取决于您。

答案 1 :(得分:3)

这是我使用的一种技术:

  1. 使控件名称属性与它们对应的数据访问对象属性的名称相同。
  2. 将它们添加到面板(ParametersPanel)
  3. 当用户单击“go”按钮时,循环遍历ParametersPanel中的控件,使用反射设置具有相应名称的数据访问对象属性。
  4. 然后,数据访问对象(或更好的数据访问框架/ api)可以根据已设置的参数动态构建查询。
  5. 硬编码巨型交换机和类似的查询通常会遇到麻烦。