假设一个基本的 3 层应用程序(UI-Service-Data Access)具有数据访问层(SQL、Xml ...)的完全抽象
UI 应用程序由具有多条件过滤器、查找等的 Datagrids 组成。
那么如何在这个架构中处理多条件查询,而不必创建多个服务方法,并将所有可能的条件作为参数......
请注意,UI 层不知道 DAL 是如何工作的。
假设一个基本的 3 层应用程序(UI-Service-Data Access)具有数据访问层(SQL、Xml ...)的完全抽象
UI 应用程序由具有多条件过滤器、查找等的 Datagrids 组成。
那么如何在这个架构中处理多条件查询,而不必创建多个服务方法,并将所有可能的条件作为参数......
请注意,UI 层不知道 DAL 是如何工作的。
这就是DTO的用途。
您可以为要过滤的每个条件创建一个对象,该对象包含类似 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 类中添加一个“运算符”字段,以允许更多的过滤选项,而不仅仅是完全匹配..
我使用 subsonic 并将 where 子句的集合传递给服务方法
我不确定这是否是您要查找的内容,但我使用 DAL 作为工厂来创建可识别 DAL 的对象,并具有合理的公共属性和/或封装各种过滤条件的方法。
要求 DAL 创建对象,根据需要编辑过滤条件,将其返回,然后让 DAL 以它需要的任何方式处理对象,以获取其给定的访问方法。
当然,这假设您没有完全开放的数据结构……您有一组已知且合理大小的可能过滤条件。如果它需要灵活到可以为未知数据结构传递任意过滤条件的程度,那么这可能不是您的解决方案。
我喜欢为此使用 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);
这可以从服务层使用,也可以从更高层使用。
有多种方法可以做到这一点,我混合使用了标准 API 和查询对象。例如,如果您有要查询的 Persons 集合:
1) 更灵活的方式criteria 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 以指示不需要该参数。
每种方法都有积极和消极的一面。