动态Entity Framework查询:Dynamic Query 介绍

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03



Dynamic Query是一个支持动态Entity Framework查询的库。它的设计初衷是为了减少在管理系统中大量出现的对一个数据集进行查找、排序、分页的这类场景的开发工作量,其设计思想是”markup is code ”。通过在View上编写具有语义信息的标签,来实现这类常见的功能需求,而不再需要额外的代码。它不是一个完整的ORM,是基于Entity Framework的,因此开发者仍然可以利用Entity Framework提供的大量特性,和现有的EF项目保持兼容。

Dynamic Query分为两个部分,其中之一是一个查询接口,这是一个IQueryable<T>的扩展方法:

public static IQueryable<T> Query<T>(this IQueryable<T> data, QueryDescriptor descriptor)

其中QueryDescriptor是一个简单的类,包含了一个查询的必要信息,例如,筛选条件,排序信息,分页信息等。

例如:

QueryDescriptor descriptor = new QueryDescriptor
            {
                OrderBy = new OrderByClause { Key = "Price", Order = OrderSequence.ASC },
                PageSize = 3,
                PageIndex = 1,
                Conditions=new QueryCondition[] {
                    new QueryCondition { Key = "Name",Value = "Rice", Operator = QueryOperator.CONTAINS }
                }
            };

            int pageCount;
            var res=ctx.Products.Query(descriptor, out pageCount);
            

这相当于执行了查询:

select * from Product where [Name] like N‘%Rice%‘ order by Price asc

并且对结果进行分页,每页3条数据,返回第一页。注意,这里返回的结果是IQueryable<T>,这实际上是一个Entity Framework的查询,在没有序列化之前,并没有对数据库进行操作,分页也是发生在服务器端的,这对于大数据来说能够极大的减少网络传输和内存使用量。 当然,手动构造这样一个QueryDescriptor也是一件非常无趣的事情,为此Dynamic Query还为asp.net MVC 实现了一系列的helper方法和一个model binder,来自动生成QueryDescriptor。我们最终的目标是获得页面提交的数据,自动生成QueryDescriptor对象。为此,需要注册一下一个自定义的binder,只需要在Global.asax的Application_Start中添加一行代码:

ModelBinders.Binders.Add(typeof(QueryDescriptor), new QueryDescriptorBinder());

假如我们有如下的EF模型:

我们来实现一个列表,对Product的Name进行筛选。这时候,可以使用QueryTextbox扩展方法来生成查询字段,View的代码如下:

<div class="container">
        <form class=".form-search">
            @Html.QueryTextbox("Name", "Product Name", QueryOperator.CONTAINS)
<input type="submit" value="Search" class="btn"/>
        </form>
</div>
<div class="row">
    <div class="span12 offset2   ">
        <table class="table table-striped">
            <thead>
                <tr>
                    <td>ID</td>
                    <td>Category</td>
                    <td>Name</td>
                    <td>Price</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tbody>
                @foreach (var p in @Model)
                {
                    <tr>
                        <td>@p.Id</td>
                        <td>@p.Category.Name</td>
                        <td>@p.Name</td>
                        <td>@p.Price</td>
                        <td>@p.Description</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
</div>

上半部分是一个form,里面有一个QueryTextBox,下半部分就是一个列表,非常简单。看对应的Action:

public ActionResult Index(QueryDescriptor descriptor)
        {
            ShopContainer ctx = new ShopContainer();
            var result = ctx.Products.Query(descriptor);
            return View("Product",result);
        }

由于Model Binder的存在,Action会从页面获得QueryDescriptor的信息。这样一个筛选页面就做好了。如果客户说,我还要增加对种类名称和价格范围的筛选,那需要改什么地方?只需要在View的form中添加几个QueryTextbox就可以了

<form class=".form-search">
            @Html.QueryTextbox("Name", "Product Name", QueryOperator.CONTAINS)
            @Html.QueryTextbox("Category.Name", "Product Category", QueryOperator.CONTAINS)
            @Html.QueryTextbox("Price.1", "Price Between", QueryOperator.GREATEROREQUAL,"decimal")
            @Html.QueryTextbox("Price.2", "", QueryOperator.LESSOREQUAL,"decimal")
            <input type="submit" value="Search" class="btn"/>
        </form>  

注意,Price出现了两次,需要加上数字后缀区分一下就可以,如果不是string类型,加上类型的说明,这样就OK。Action方法是不需要有任何改动的。

如果客户说这个要分页怎么办? 分页需要稍微多些两行代码,但是也只需要2分钟就足够,先看Action方法:

public ActionResult Product(QueryDescriptor descriptor)
        {
            descriptor.PageSize = 5;
            descriptor.OrderBy = new OrderByClause { Key = "Id", Order = OrderSequence.ASC };

            ShopContainer ctx = new ShopContainer();
            int pageCount;
            var result = ctx.Products.Query(descriptor, out pageCount);
            Pager pager = new Pager(pageCount, descriptor);
            ViewBag.Pager = pager;
            return View("Index",result);
        }

首先指定一页显示的数量,因为要分页,必须要有排序信息,这里是根据Id,升序排列。接下来还是调用Query方法获得数据,注意,这里是Query的一个重载的方法,能够返回总共有多少页,这一般是分页控件需要的信息。接下来实例化一个Pager对象,这个Pager是一个分页器,包含在Dynamic Query中,如果你想用其他第三方的分页器,也是可以的。Pager需要的额外信息就是总页数,把这个Pager放到ViewBag上面,然后Action的工作就完成了。View上面也不想要任何改变,如果你想加上分页链接的话,只需要一行代码:

@Html.QueryPager((Pager)ViewBag.Pager); 

看看效果:

项目主页和源代码在:http://dynamicquery.codeplex.com/  上面有一个样例程序,更多文档在完善中。

这个项目才开始没多久,还有很多细节需要完善,主要是样式、支持更多的控件,比如checkbox,dropdownlist等。以后慢慢补充。

参考页面:http://qingqingquege.cnblogs.com/p/5933752.html

时间: 2024-10-19 21:55:44

动态Entity Framework查询:Dynamic Query 介绍的相关文章

第二篇 Entity Framework Plus 之 Query Future

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 从性能的角度出发,能够减少 增,删,改,查,跟数据库打交道次数,肯定是对性能会有所提升的(这里单纯是数据库部分). 今天主要怎样减少Entity Framework查询跟数据库打交道的次数,来提高查询性能. 举一个大家最常用功能 "分页&quo

Entity Framework查询注意

首先我们看下where的方法,直接查看定义(定义如下),其实一种是对IEnumerable的扩展,一种是对IQueryable的扩展,直接看最常用的,其实区别就在IEnumerable的扩展的参数是系统定义的委托Func<TSource,bool> IQueryable的参数则是表达式Expression<Func<TSource,bool>>, 1.IEnumerable<TSource> Where<TSource>(this IEnumer

Entity Framework 6.1-Database First介绍

原文:Entity Framework 6.1-Database First介绍 这种方式是比较传统的以数据库为核心的开发模式.比较适合有数据库DBA的团队.或者数据库已存在的情况. 优缺点: 1.优点:编辑代码最少的方式,在有完整的数据库的前提下,你几乎可以不编辑任何代码就能完成应用程序的数据层部分(EF). 2.不够灵活,域模型结构完全由数据库控制生成,结构不一定合理:受数据库表和字段名影响,命名不规范. 创建步骤:1.在程序中新建DAL文件夹(或者单独创建DAL工程), 2.DAL文件夹点

Entity Framework查询生成大量的子查询,如何避免?求救

最近使用Entity Framework做一个中型的项目,一张表含有千万条数据,并没有使用很复杂的查询,只是程序上使用了DTO进行帅选数据,且使用了分页,效果很不理想.经过跟踪sql,我发现很多简单的查询,都存在子查询,而子查询往往会影响到查询性能,在这里,我想问问大虾,除了自己写SQL语句,有没有更好的解决办法在Entity Framework基础上处理这个问题? 如图所示: Entity Framework查询代码 private async Task<QuotationDto[]> Ge

[原创]Entity Framework查询原理

前言 Entity Framework的全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Relational Mapping)框架.Entity Framework的主要特点:1. 支持多种数据库(Microsoft SQL Server, Oracle, and DB2):2. 强劲的映射引擎,能很好地支持存储过程:3. 提供Visual Studio集成工具,进行可视化操作:4. 能够与ASP.NET, WPF, WCF, WCF

一个最简单的使用Entity Framework 查询SQL 数据库的例子

1.ADO.NET 3.5 Entity Framework是随着.net framework 3.5一起发布的,确认开发环境版本是大于等于3.5版本 2.确认已经安装了ADO.NET 3.5 Entity Framework 和ADO.NET 3.5 Entity Framework Tools:右键单击创建的winform或者wpf程序,选择"Add|New Item",查看Templates 列表框中是否有ADO.NET Entity Data Model,如果没有,请到此网址下

Entity Framework查询,EF执行SQl

一.简介 EF 支持开放底层的 ADO.NET 框架,DbContext有三种常用方法 DbSet.SqlQuery //查询并返回Entities DbContext.Database.SqlQuery<T> //执行某一个查询,并可以将返回集转换为某一对象 DbContext.Database.ExecuteSqlCommand //执行某一并无返回集的SQL 命令,例如UPDATE,DELETE操作 二.用法 1.DbSet.SqlQuery用法 var list = db.admins

Entity Framework Core 之简单介绍

Overview EFCore是一个以对象映射器(O/RM)为核心的轻量级.可扩展的实体框架数据访问技术,目前支持Microsoft SQL Server.SQLite.Postgres(Npgsql).InMeory等数据库技术 获取EntityFramework Core方法:通过Nuget package安装或使用命令安装SQLSERVER Concepts EntityState 跟EF6.X一样,这里也存在EntityState 成员名称 说明 Added 对象为新对象,且已添加到对象

LINQ TO SQL和Entity Framework 的关系 你了解多少?

1. LINQ  TO SQL 和EF 特点:  LINQ TO SQL和Entity Framework都是一种包含LINQ功能的ORM 也就是所谓的关系对象的映射.其中包括的有DBFrist  Code Frist    ModeL  Frist   三种中方式 来进行和数据库之间的访问.只是形式不同而已本质没有什么区别.都是ORM  之间的转化.最终都是来进行访问底层的数据库的对象 和服务. 简单来说LINQ是为了满足不知道怎么操作数据库的程序员开发设计的,LinQ 可以让他们以一种面向数