C# 如何在三层体系结构中处理多标准查询

C# 如何在三层体系结构中处理多标准查询,c#,architecture,3-tier,C#,Architecture,3 Tier,假设一个基本的三层应用程序(UI服务数据访问)具有数据访问层(SQL、Xml…)的总体抽象 UI应用程序由带有多标准过滤器、查找等的数据网格组成 因此,如何在该体系结构中处理多标准查询,而不必创建多个服务方法,将所有可能的标准作为参数 请注意,UI层不知道DAL是如何工作的。我使用亚音速并将where子句的集合传递给服务方法,这就是a的用途。我不确定这是否是您正在寻找的,但我使用DAL作为工厂来创建DAL感知对象,具有合理的公共属性和/或封装各种筛选条件的方法 要求DAL创建对象,根据需要编辑筛

假设一个基本的三层应用程序(UI服务数据访问)具有数据访问层(SQL、Xml…)的总体抽象

UI应用程序由带有多标准过滤器、查找等的数据网格组成

因此,如何在该体系结构中处理多标准查询,而不必创建多个服务方法,将所有可能的标准作为参数


请注意,UI层不知道DAL是如何工作的。

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

,这就是a的用途。

我不确定这是否是您正在寻找的,但我使用DAL作为工厂来创建DAL感知对象,具有合理的公共属性和/或封装各种筛选条件的方法

要求DAL创建对象,根据需要编辑筛选条件,将其返回,并让DAL以其给定访问方法所需的任何方式处理对象


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

您可以为要筛选的每个条件创建一个对象,其中包含类似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; }
}
类多准则过滤
{
清单标准;
//这个方法只是为了简单而放在这里——它应该在DAL中,而不是DTO中
字符串BuildWhereCondition()
{
StringBuilder条件=新建StringBuilder();
条件.Append(“其中(1=1)”
foreach(标准中的过滤标准)
{
条件.Append(“AND”).Append(criteria.FieldName).Append(=”);
条件.Append(“”).Append(criteria.FilterValue).Append(“”);
}
返回条件.ToString();
}
}
类过滤标准
{
字符串字段名{get;set;}
对象筛选器值{get;set;}
}

您可以很容易地对此进行扩展,例如,在FilterCriteria类中添加一个“operator”字段,以允许更多的筛选选项,而不仅仅是精确匹配。

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

e、 g


CustomerDTO示例=新建CustomerDTO();
example.lastName=“jones”
AddressDTO exAddr=新的AddressDTO();
exAddr.city=“波士顿”;
示例.address.add(exAddr)

var customers=svc.GetCustomersLike(示例);

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

查看Rob的。它使用一个模型,该模型从DAL向上传递,通过服务层,甚至在UI层中使用。这没关系,并且不会打破UI不知道DAL是如何实现的要求。您可以轻松地将域模型移动到另一个VS上如果您希望第三方应用程序访问您的服务层而不知道DAL是如何工作的,请进行project


有一些关于将LinqToSql函数抽象到更高层的方法的详细信息。如果你像我一样喜欢LinqToSql的延迟执行功能,但你不希望你的应用程序依赖LinqToSql作为数据提供程序,你可能会想这样做。

有多种方法,我混合使用了criteria API和查询对象。 例如,如果您有要查询的人员集合:

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

对值类型使用Nullable,并分配Null以指示不需要该参数


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

您如何处理?是否将SQL where子句传递给服务方法?我的UI层不知道DAL是如何工作的,因此我无法通过我的服务方法传递普通的SQL where子句。您必须与客户端共享DAL才能使其工作。它不是很“纯”,但效果很好。你只需要知道你不能从客户端调用CRUD方法。@ptutt不,我不能与客户端共享DAL。我认为这不是一个伟大的建筑设计。客户机只与服务层(业务)对话您可以将DAL中的表定义类(即dto)和where子句类拆分为一个单独的程序集,该程序集可以在客户机和服务器之间共享。@Yoann:我认为ptutt的意思是您需要与客户机共享模型对象(dto)。这些可能在您的DAL项目中,也可能不在您的DAL项目中,当然也不是您的数据访问实现(我认为您参考的是“不是一个伟大的架构设计”),所以您在这方面还可以。@Beska我需要一种通用和抽象的方法来处理多标准查询。但不是像这样的具体方法:public-IList-FindSomething(int-filter1,string-filter2…),但可能是一种更灵活的LINQ表达式方式,比如:public-IList-Find(Expression-filters[]),我不知道……我有一个类似的问题,这里有一个begging,但太“依赖SQL”。。。
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).
}
public class PersonQuery
{
 Guid? Id;
 GenderEnum? Gender;
 Int32? Age;
 Int32? AgeMin;
 Int32? AgeMax;
 String Name;
 String NameContains;
 Person FatherIs;
 Person MotherIs;
 //...
}