UI应用程序由带有多个条件过滤器、查找等功能的数据网格组成。
那么,在不必创建具有所有可能参数的多个服务方法的情况下,如何处理这种体系结构中的多条件查询...
请注意,UI层不知道DAL的工作原理。
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; }
}
有多种方法可以做到这一点,我使用了标准 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来指示参数不是必需的。
每种方法都有积极和消极的方面。
我使用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);
这可以从服务层或更高层使用。
看看Rob的Storefront教程。它使用了一个模型,从DAL传递到服务层,甚至在UI层中使用。这是可以的,并且不会违反您的要求,即UI不能知道如何实现DAL。如果您希望第三方应用程序访问您的服务层而不知道DAL的工作方式,您可以轻松地将域模型移动到另一个VS项目中。
这个答案有一些关于如何在更高层次上抽象LinqToSql函数的细节。如果像我一样,您喜欢LinqToSql的延迟执行功能,但又不想让您的应用程序依赖于LinqToSql作为数据提供程序,那么您可能需要这样做。