如何在 3 层架构中处理多条件查询

Posted

技术标签:

【中文标题】如何在 3 层架构中处理多条件查询【英文标题】:How-To Deal with Multi-Criteria Queries in 3-Tier Architecture 【发布时间】:2010-12-11 18:05:50 【问题描述】:

假设一个基本的 3 层应用程序(UI-Service-Data Access)具有数据访问层(SQL、Xml ...)的完全抽象

UI 应用程序由具有多条件过滤器、查找等的 Datagrids 组成。

因此,如何在此架构中处理多条件查询,而无需创建多个服务方法,并将所有可能的条件作为参数...

请注意,UI 层不知道 DAL 的工作原理。

【问题讨论】:

我也有类似的问题 这是一个开始但也“依赖于 SQL”...drewnoakes.com/code/util/Filter.html 【参考方案1】:

这就是DTO 的用途。

【讨论】:

【参考方案2】:

我使用 subsonic 并将 where 子句的集合传递给服务方法

【讨论】:

你如何处理这个?您将 SQL where 子句传递给服务方法?我的 UI 层不知道 DAL 是如何工作的,所以我不能通过我的服务方法传递普通的 SQL where 子句。 您已与客户端共享 DAL 以使其正常工作。它不是真正的“纯”,但效果很好。你只需要知道你不能从客户端调用 CRUD 方法。 @ptutt 不,我无法与客户端共享 DAL。我认为这不是一个伟大的架构设计。客户端只与服务层(业务)对话 您可以将 DAL 中的表定义类(即 dto)和 where 子句类拆分为一个单独的程序集,该程序集可以在客户端和服务器之间共享。 @Yoann:我认为 ptutt 的意思是您需要与客户端共享模型对象 (DTO)。这些可能在您的 DAL 项目中,也可能不在您的 DAL 项目中,当然也不是您的数据访问实现(我认为这是您所指的“不是一个伟大的架构设计”),所以你没问题。【参考方案3】:

我不确定这是否是您要查找的内容,但我使用 DAL 作为工厂来创建可识别 DAL 的对象,该对象具有合理的公共属性和/或封装各种过滤条件的方法。

要求 DAL 创建对象,根据需要编辑过滤条件,将其返回,然后让 DAL 以它需要的任何方式处理对象,以获取其给定的访问方法。

当然,这假设您没有完全开放的数据结构......您有一组已知且合理大小的可能过滤条件。如果它需要灵活到可以为未知数据结构传递任意过滤条件的程度,那么这可能不是您的解决方案。

【讨论】:

@Beska 我需要一种通用且抽象的方式来处理多条件查询。但不是这样的具体方法: public IList FindSomething(int filter1, string filter2 ...) 但也许是使用 LINQ 表达式的更灵活的方法,例如: public IList Find(Expression filters[]) 我不知道.. .【参考方案4】:

您可以为要过滤的每个条件创建一个包含 KeyValuePair 之类的对象。然后,您的 DAL 可以从中构建 where 条件..

像这样:

class MultiCriteriaFiltering

    List<FilterCriteria> Criterias;

    // this method just sits here for simplicity - it should be in your DAL, not the DTO
    string BuildWhereCondition()
    
        StringBuilder condition = new StringBuilder();
        condition.Append("WHERE (1=1) "
        foreach (FilterCriteria criteria in Criterias)
        
            condition.Append(" AND ").Append(criteria.FieldName).Append(" = ");
            condition.Append("'").Append(criteria.FilterValue).Append("'");
        
        return condition.ToString();
    


class FilterCriteria

    string FieldName  get; set; 
    object FilterValue   get; set; 

您可以很容易地对此进行扩展,例如向 FilterCriteria 类添加一个“运算符”字段,以允许更多过滤选项,而不仅仅是完全匹配。

【讨论】:

【参考方案5】:

我喜欢为此使用 Query-By-Example。在这里您可以传入一个实际示例 DTO,并且任何非默认值字段都表示查询条件。

例如

CustomerDTO example = new CustomerDTO(); example.lastName = "jones"; AddressDTO exAddr = new AddressDTO(); exAddr.city = "Boston"; example.addresses.add(exAddr);

var customers = svc.GetCustomersLike(example);

这可以从服务层使用,也可以从更高的层使用。

【讨论】:

【参考方案6】:

查看 Rob 的 Storefront tutorial。它使用从 DAL 向上传递的模型,通过服务层甚至在 UI 层中使用。这没关系,并且不会破坏 UI 无法知道 DAL 是如何实现的要求。如果您希望 3rd 方应用程序访问您的服务层并且不知道 DAL 的工作原理,您可以轻松地将您的域模型移动到另一个 VS 项目。

This answer 有一些关于在更高层抽象 LinqToSql 函数的方法的详细信息。如果您像我一样喜欢 LinqToSql 的延迟执行功能,但又不希望您的应用依赖 LinqToSql 作为数据提供者,那么您可能想要这样做。

【讨论】:

【参考方案7】:

有多种方法可以做到这一点,我混合使用了标准 API 和查询对象。 例如,如果您有要查询的 Persons 集合:

1) 更灵活的标准API方式:GetPerson(IList query)

public class Criteria

 Object Property; // (Domain property, not DB)// (String Or Lambda) Age, Father.Age, Friends, etc
 Object Operator; //(Enum or String)(Eq, Gr, Between,Contains, StartWith, Whatever...)
 Object Value; // (most likely Object, or use generics Criteria<T>), (Guid, int[], Person, any type).

2) 强描述查询对象:

public class PersonQuery

 Guid? Id;
 GenderEnum? Gender;
 Int32? Age;
 Int32? AgeMin;
 Int32? AgeMax;
 String Name;
 String NameContains;
 Person FatherIs;
 Person MotherIs;
 //...

对值类型使用 Nullable 并分配 Null 以指示该参数不是必需的。

每种方法都有积极和消极的一面。

【讨论】:

以上是关于如何在 3 层架构中处理多条件查询的主要内容,如果未能解决你的问题,请参考以下文章

jsp如何按指定条件进行模糊查询

jsp 多条件查询。

关于SQL多条件查询问题: 若其中一条件为空值如何设置忽略该条件而用其它条件组合查询??

jsp多条件查询问题,请高手指点迷津!

MyBatis模糊查询和多条件查询

jsp 多条件组合查询