65.9K
CodeProject 正在变化。 阅读更多。
Home

用于开发 .NET 业务 Web 窗体的创新架构 (2) - 如何实现查询

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (7投票s)

2010年3月8日

GPL3

5分钟阅读

viewsIcon

29287

本系列文章介绍了一种用于企业软件开发中开发业务 Web 窗体的创新架构,与传统的 ASP.NET 或 MVC 开发相比,它具有更好的性能、更高的生产力、更强的可配置性和更易于维护性。

引言

本系列文章介绍了一种用于企业软件开发中开发业务 Web 窗体的创新架构,与传统的 ASP.NET 或 MVC 开发相比,它具有更好的性能、更高的生产力、更强的可配置性和更易于维护性。这是本系列的第二篇文章。在继续之前,您应该在 <<RapidWebDevUI 概述>> 中查看第一篇文章以了解概念和概览。本文将介绍“查询”的工作原理以及如何在 Web 窗体中配置查询面板。

“查询”的工作原理

查询面板的开发由 XML 配置和对接口 IDynamicPageQuery 方法的实现组成,如下面的代码片段所示。

<QueryPanel HeaderText="Query Users">
    <TextBox FieldName="UserName" Label="UserName: " />
    <TextBox FieldName="DisplayName" Label="DisplayName: " />
    <CheckBoxGroup FieldName="Membership.IsApproved" 
        FieldValueType="System.Boolean" Label="Approved: " Occupation="1">
        <Item Text="Yes" Value="true" Checked="true" />
        <Item Text="No" Value="false" />
    </CheckBoxGroup>
</QueryPanel>
/// <summary>
/// Execute query for results binding to dynamic page grid.
/// </summary>
/// <param name="parameter">Query parameter.</param>
/// <returns>Returns query results.</returns>
QueryResults Query(QueryParameter parameter);

RapidWebDev UI 框架根据 QueryPanel XML 元素中的过滤器进行配置来渲染查询面板的 UI。默认支持的查询过滤器控件类型有 CheckBoxCheckBoxGroupComboBoxDateDateTimeIntegerDecimalTextBoxRaduiGroup。当所有这些控件都不能满足您的要求时,您可以使用 Custom XML 元素来配置您开发的自定义查询过滤器控件,该控件遵循自定义查询过滤器控件的规范。如上文的查询面板配置所示,渲染的 UI 如下面的屏幕截图所示。

RapidWebDev UI 框架渲染查询面板的 UI 时,有一个 JavaScript 管理器实例为查询面板注册到 Web 浏览器中,该管理器负责管理所有查询过滤器,包括它们的状态和值。当单击“查询”按钮时,查询面板管理器实例会收集每个查询过滤器的用户输入,并组装一个异步 HTTP 请求发送到动态页面的 RapidWebDev 数据服务以获取 JSON 数据响应,例如~/ObjectId/DynamicPageDataService.svc。我使用 Fiddler2 跟踪 HTTP 请求和响应,如下面的屏幕截图所示。返回 4 条记录的数据响应仅为 **2.5KB**。

最后,查询面板管理器将 JSON 数据渲染到网格中。

查询面板 XML 配置

上面提到的默认支持的查询过滤器控件类型具有通用属性,如 LabelFieldNameOperatorFieldValueTypeOccupation
Label 是 UI 中查询过滤器的标签,例如“用户名:”。Label 支持变量标记,如 $VariableName$ 或“$Namespace.ClassName.StaticPropertyName, AssemblyName$”。VariableName 应通过接口 IDynamicPageSetupContextTempVariables 方法进行设置。

FieldName 用于框架通过 IPredicateCompiler (命名空间:RapidWebDev.UI.DynamicPages)的实现自动组装查询表达式。它支持关联对象的属性。例如,我们配置一个动态页面来管理用户,页面的主要入口是 User。实体 User 引用 Membership。我们希望通过 Membership 的属性(如上面代码片段中的 Membership.IsApproved)来查询用户。Linq2SQL 谓词编译器(类:RapidWebDev.UI.DynamicPages.Linq2SQLPredicateCompiler)将查询过滤器编译为表达式,如

var query = from user in dataContext.Users
    where user.Membership.IsApproved
	select user;

Operator 是查询条件的运算符,支持 EqualStartsWithLikeInNotInGreaterThanGreaterEqualThanLessThanLessEqualThanBetween。默认情况下,框架根据查询过滤器控件类型选择运算符。

FieldValueType 是查询表达式参数值的 CLR 类型。如果指定了 FieldValueType,则在组装查询表达式时,查询过滤器控件的值将被隐式转换为目标类型。

Occupation 指示查询过滤器控件在渲染的查询面板中占用多少单元格。例如,查询面板布局实现 TableXColumnsQueryPanelLayout 在 HTML table 中渲染所有查询过滤器。Occupation 表示查询过滤器控件占用的列数。

除了这些通用属性外,最好查看 DynamicPage.xsd 以了解每个查询过滤器控件的扩展属性。

查询实现

RapidWebDev 动态页面的数据服务将异步查询请求转换为 QueryParameter,其中包含查询和排序信息。QueryParameter 可以通过 IPredicateCompiler (命名空间:RapidWebDev.UI.DynamicPages)的实现转换为查询和排序表达式,该实现已在 Spring.NET IoC 中配置。如下面查询产品的实现所示,我们只需要将编译后的查询和排序表达式与 Linq2SQL lambda 表达式进行转换和连接。而无需显式组装查询表达式。因此,我们可以轻松处理查询过滤器的需求变更,而无需重新编译。返回的 QueryResults(int recordCount, IEnumerable results) 会被框架自动序列化为 JSON 数据。

/// <summary>
/// Query products by parameters.
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public override QueryResults Query(QueryParameter parameter)
{
    using (ProductManagementDataContext ctx = 
        DataContextFactory.Create<ProductManagementDataContext>())
    {
        IQueryable<Product> q = from p in ctx.Products 
                                where p.ApplicationId == 
				authenticationContext.ApplicationId 
                                select p;

        LinqPredicate predicate = parameter.Expressions.Compile();
        if (predicate != null && !string.IsNullOrEmpty(predicate.Expression))
            q = q.Where(predicate.Expression, predicate.Parameters);

        if (parameter.SortExpression != null)
            q = q.OrderBy(parameter.SortExpression.Compile());

        int recordCount = q.Count();
        var results = q.Skip(parameter.PageIndex * parameter.PageSize)
            .Take(parameter.PageSize).ToList();
        return new QueryResults(recordCount, );
    }
}

动态数据

我们可能需要动态支持 XML 中无法配置的需求,例如,为具有不同权限的用户渲染不同的查询过滤器,或者查询面板中下拉列表框的项应从数据库中获取。 RapidWebDev 支持此类场景。动态页面的 XML 配置可以配置一个回调函数,在 UI 渲染之前更改配置,请参阅 DynamicPage.xsd 中的 Page/@ProcessCallbackType。我们可以在回调函数中在运行时更改配置。此外,我们可以为下拉列表框查询过滤器配置 DynamicDataSourceDynamicDataSource 被配置为从 JSON 驱动的外部 Web 服务拉取项,如下面的代码片段所示。因此,在该示例中,当用户选择或在可编辑的 combobox 中输入文本时,combobox 会从外部服务刷新匹配的项。

<ComboBox FieldName="ParentHierarchyDataId" Label="Parent: " Editable="true" 
    MinChars="2" FieldValueType="System.Guid" ForceSelection="true">
    <DynamicDataSource Url=
	"/Services/HierarchyService.svc/json/FindByKeyword?limit=999" 
	    Method="GET" TextField="Name" ValueField="Id" QueryParam="q">
        <Param Name="hierarchyType" Value="$HierarchyType$" />
    </DynamicDataSource>
</ComboBox> 

查询面板布局

IQueryPanelLayout 接口用于渲染查询面板的布局。 RapidWebDev 在 1.51 版本中实现了一个基于 html table 的布局,称为 RapidWebDev.UI.DynamicPages.TableXColumnsQueryPanelLayout。如果您有其他需求,可以实现一个新的策略并将其配置到 Spring.NET IoC 中,而不是当前 RapidWebDev.Web\Spring\ui.config 中的 TableXColumnsQueryPanelLayout

什么是RapidWebDev

网站: http://www.rapidwebdev.org

RapidWebDev 是一个基础设施,可帮助工程师轻松高效地开发 Microsoft .NET 中的企业软件解决方案。它由一个可扩展且可维护的 Web 系统架构组成,包含一套通用的业务模型、API 和服务,作为开发几乎所有业务解决方案所需的基本功能。因此,当工程师使用 RapidWebDev 进行开发时,他们可以获得许多可重用且现成的东西,然后可以更专注于业务逻辑的实现。实际上,与传统的 ASP.NET 开发相比,我们可以节省超过 50% 的时间来开发高质量、高性能的业务解决方案。

相关主题

© . All rights reserved.