如何在 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您可以为要过滤的每个条件创建一个包含 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 层架构中处理多条件查询的主要内容,如果未能解决你的问题,请参考以下文章