Chapter Querying Data
Chapter Querying Data
XF获取数据的三种方法:
其中参数schema,参见 Chapter Schema。
下面列出一个后面将会用到的schema片段,称之为片段A:
<User Set="Users">
...
<Employee.Name Element="Employee" Field="Name" />
...
</User>
方法一:ElementQuerier.GetSet("User", "Id,UserName,IsLockedOut,Employee.Name", "EmployeeId eq 1", "Id desc", schema);
内部会调用3.调用时,已在schema插入片段A。
方法二:.Linq,需要using XData.Data.Query。返回 XElement。
ElementContext.GetElementSet("User", schema)
.Where(x => x.Element("EmployeeId").Value == "1")
.OrderByDescending(x => int.Parse(x.Element("Id").Value))
.Select(x => new XElement(x.Name, x.Element("Id"), x.Element("UserName"), x.Element("IsLockedOut"), x.Element("Employee.Name")));
内部会调用3.调用时,schema 中应有片段A。
方法三:.ElementContext.GetSet(query, schema);返回 XElement。
schema 中应有片段A。
参数query:
<User>
<Select>
<Id />
<UserName />
<IsLockedOut />
<Employee.Name />
</Select>
<OrderByDescending>
<Id />
</OrderByDescending>
<!-- Linq -->
<Where>
<BinaryExpression NodeType="Equal">
<MemberExpression NodeType="MemberAccess" Member="Id" />
<ConstantExpression NodeType="Constant" DataType="System.Int32" Value="1" />
</BinaryExpression>
</Where>
<!-- ElementQuerier -->
<Filter>
<Value>EmployeeId eq 1</Value>
</Filter>
</User>
直接的Sql
Database.SqlQuery("User",
"SELECT u.Id,u.UserName,u.IsLockedOut,e.Name [Employee.Name] FROM Users u LEFT JOIN Employees e ON u.EmployeeId = e.Id WHERE u.EmployeeId = 1 ORDER BY u.Id DESC;");返回 IEnumerable<XElement>
比较发现,方法二Linq不够简洁,方法三过于底层。因此更为推荐方法一。以下叙述,均以方法一为主。
ElementQuerier设计极力模仿OData,称之为XData(将在XData介绍)。下面列出XData支持的操作符和函数:
Operators:
|
OData |
SQL Server |
OData |
SQL Server |
|
eq |
= |
IsLockedOut eq true |
IsLockedOut = 1 |
|
eq null |
IS NULL |
Descr eq null |
Descr IS NULL |
|
ne |
!= |
Name ne 'Milk' |
Name != 'Milk' |
|
ne null |
IS NOT NULL |
Descr ne null |
Descr IS NOT NULL |
|
gt |
> |
Id gt 1 |
Id > 1 |
|
ge |
>= |
CreatedDate ge datetime’2012-12-1’ |
CreatedDate >= ’2012-12-1’ |
|
lt |
< |
Allowance lt 1000 |
Allowance < 1000 |
|
le |
<= |
Allowance le 1000.1 |
Allowance <= 1000.1 |
|
and |
AND |
(IsLockedOut eq true) and (Id eq 1) |
(IsLockedOut = 1) and (Id = 1) |
|
or |
OR |
(Id gt 1) OR (Allowance le 1234.56) |
(Id > 1) OR (Allowance <= 1234.56) |
|
not |
NOT |
not (Id gt 1) |
NOT (Id > 1) |
|
has |
Not supported |
has |
Not supported |
|
add |
+ |
Allowance add 12.34 |
Allowance + 12.34 |
|
sub |
- |
Allowance sub 12.34 |
Allowance - 12.34 |
|
mul |
* |
Allowance mul 2.15 |
Allowance * 2.15 |
|
div |
/ |
Allowance div 2.0 |
Allowance / 2.0 |
|
mod |
% |
Rating mod 5 |
Rating % 5 |
Canonical Functions:
|
OData |
SQL Server |
OData |
SQL Server |
|
contains(XData) |
Operator IN |
contains((1,3,5),Id) |
Id IN (1,3,5) |
|
contains |
Operator LIKE |
contains(CompanyName,'Alfreds') |
CompanyName LIKE '%Alfreds%' |
|
endswith |
Operator LIKE |
endswith(CompanyName,'Futterkiste') |
CompanyName LIKE '%Futterkiste' |
|
startswith |
Operator LIKE |
startswith(CompanyName,'Alfr') |
CompanyName LIKE 'Alfr%' |
|
length |
DATALENGTH |
length(CompanyName) |
DATALENGTH(CompanyName) |
|
indexof |
CHARINDEX |
indexof(CompanyName,'lfreds') |
CHARINDEX('lfreds', CompanyName) -1 |
|
substring |
SUBSTRING |
substring(CompanyName, 1) |
SUBSTRING(CompanyName, 2, 2147483647) |
|
substring |
SUBSTRING |
substring(CompanyName, 1, 2) |
SUBSTRING(CompanyName, 2, 2) |
|
tolower |
LOWER |
tolower(CompanyName) |
LOWER(CompanyName) |
|
toupper |
UPPER |
toupper(CompanyName) |
UPPER(CompanyName) |
|
trim |
LTRIM and RTRIM |
trim(CompanyName) |
LTRIM(RTRIM(CompanyName)) |
|
concat(XData) |
Operator + |
concat(City, ', ', Country) |
City + ', ' + Country |
|
year |
DATEPART |
year(BirthDate) |
DATEPART(YEAR, BirthDate) |
|
month |
DATEPART |
month(BirthDate) |
DATEPART(MONTH, BirthDate) |
|
day |
DATEPART |
day(BirthDate) |
DATEPART(DAY, BirthDate) |
|
hour |
DATEPART |
hour(BirthDate) |
DATEPART(HOUR, BirthDate) |
|
minute |
DATEPART |
minute(BirthDate) |
DATEPART(MINUTE, BirthDate) |
|
second |
DATEPART |
second(BirthDate) |
DATEPART(SECOND, BirthDate) |
|
fractionalseconds |
DATEPART |
fractionalseconds(BirthDate) |
DATEPART(MILLISECOND, BirthDate) /1000.0 |
|
date |
CAST and CONVERT |
date(BirthDate) |
CAST(CONVERT(char(10), BirthDate,120) AS datetime) |
|
time |
Not supported |
time(BirthDate) |
Not supported |
|
totaloffsetminutes |
Not supported |
totaloffsetminutes(datetime) |
Not supported |
|
now |
GETDATE |
now() |
GETDATE() |
|
Utcnow(XData) |
GETUTCDATE |
utcnow() |
GETUTCDATE() |
|
maxdatetime |
Not supported |
maxdatetime() |
Not supported |
|
mindatetime |
Not supported |
mindatetime() |
Not supported |
|
totalseconds |
Not supported |
totalseconds |
Not supported |
|
round |
ROUND |
round(Amount) |
ROUND(Amount, 0) |
|
floor |
FLOOR |
floor(Amount) |
FLOOR(Amount) |
|
ceiling |
CEILING |
ceiling(Amount) |
CEILING(Amount) |
|
isof |
Not supported |
isof |
Not supported |
|
cast |
Not supported |
cast |
Not supported |
注:现在明白古怪的"EmployeeId eq 1"是什么了吧。
高阶ElementQuerier(XData)查询
调用如下方法,会返回一个“聚合”结构的XElement:
ElementQuerier.GetSet("Job","Id,Name","Allowance gt 0",null, expands,schema);
参数schema,如前。
参数expands,类型为IEnumerable<Expand>,其内容为:

仔细查看返回的XElement,重点查看层次结构:
<Jobs>
<Job>
<Id>1</Id>
<Name>CEO</Name>
<Employees>
<Employee>
<Id>1</Id>
<Name>Carl Zeiss</Name>
<JobId>1</JobId>
<Users>
<User>
<Id>1</Id>
<UserName>Carl</UserName>
</User>
<User>
<Id>5</Id>
<UserName>Admin</UserName>
</User>
</Users>
</Employee>
</Employees>
</Job>
<Job>
<Id>2</Id>
<Name>CFO</Name>
<Employees>
<Employee>
<Id>2</Id>
<Name>Cherry Wong</Name>
<JobId>2</JobId>
<Users>
<User>
<Id>2</Id>
<UserName>Cherry</UserName>
</User>
</Users>
</Employee>
</Employees>
</Job>
</Jobs>
如前所述,ElementQuerier.GetSet内部会调用ElementContext.GetSet,这里也是一样,在调用前会将下列片段B,插入schema参数中。
schema 片段B:
<Job Set="Jobs">
...
<Employees Element="Employee">
<Users Element="User" Select="Id,UserName" />
</Employees>
...
</Jobs>
注:上述方法,其实由下面这个链接引发。
http://localhost:2012/XData/Jobs?$expand=Employees($expand=Users($select=Id,UserName))&$select=Id,Name&$filter=Allowance%20gt%200
上面为master -details,再来看一个detail-master 查询,注意$filter里面的Job与User没有直接关系,而是通过ReferencePath连接:
http://localhost:2012/XData/Users?$expand=Employee&$select=Id,EmployeeId,UserName&$filter=Job.Allowance%20gt%200
返回结果:
<Users>
<User>
<Id>1</Id>
<EmployeeId>1</EmployeeId>
<UserName>Carl</UserName>
<Employee>
<Id>1</Id>
<Name>Carl Zeiss</Name>
<JobId>1</JobId>
</Employee>
</User>
<User>
<Id>2</Id>
<EmployeeId>2</EmployeeId>
<UserName>Cherry</UserName>
<Employee>
<Id>2</Id>
<Name>Cherry Wong</Name>
<JobId>2</JobId>
</Employee>
</User>
<User>
<Id>5</Id>
<EmployeeId>1</EmployeeId>
<UserName>Admin</UserName>
<Employee>
<Id>1</Id>
<Name>Carl Zeiss</Name>
<JobId>1</JobId>
</Employee>
</User>
</Users>
多对多关系的查询:
http://localhost:2012/XData/Users?$select=Id,UserName&$filter=Id%20lt%203&$expand=Roles($select=Id,RoleName)
返回结果:
<Users>
<User>
<Id>1</Id>
<UserName>Carl</UserName>
<Roles>
<Role>
<Id>1</Id>
<RoleName>Admin</RoleName>
</Role>
<Role>
<Id>2</Id>
<RoleName>User</RoleName>
</Role>
</Roles>
</User>
<User>
<Id>2</Id>
<UserName>Cherry</UserName>
<Roles>
<Role>
<Id>2</Id>
<RoleName>User</RoleName>
</Role>
</Roles>
</User>
</Users>
XF遇到多对多关系“连接”就此“断路”,所以以下查询是错误的:
http://localhost:2012/XData/Users?$select=Id,UserName&$filter=Id%20lt%203&$expand=Roles($select=Id,RoleName$expand=Routes)
ElementQuerier 除了上面介绍的GetSet,还有下列主要方法:
public XElement Find(string elementName, string[] key, string select, XElement schema)
public XElement Find(string elementName, string[] key, string select, IEnumerable<Expand> expands, XElement schema)
public XElement GetPage(string elementName, string select, string filter, string orderBy, int skip, int take, XElement schema)
public XElement GetPage(string elementName, string select, string filter, string orderBy, int skip, int take, IEnumerable<Expand> expands, XElement schema)
public int GetCount(string elementName, string filter, XElement schema)
public XElement GetDefault(string elementName, string select, XElement schema)
为什么会有GetDefault方法,见如下查询的结果:
http://localhost:2012/XData/Employees/$default?$select=Id,Name,JobId,Jobs.Name
注意下面的Jobs.Name,它是通过"Where JobId = 3"查询得到的。
<Employees>
<Id/>
<Name/>
<JobId>3</JobId>
<Jobs.Name>Clerk</Jobs.Name>
</Employees>
Chapter Querying Data的更多相关文章
- 《Pro SQL Server Internals, 2nd edition》的CHAPTER 1 Data Storage Internals中的Data Pages and Data Rows(翻译)
数据页和数据行 数据库中的空间被划分为逻辑8KB的页面.这些页面是以0开始的连续编号,并且可以通过指定文件ID和页号来引用它们.页面编号都是连续的,这样当SQL Server增长数据库文件时,从文件中 ...
- AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) Chapter 3. Data Structures Fundamental Data Structures
10410 这题说的是给了一棵多叉树的 bfs遍历轨迹 和dfs 遍历 轨迹 在父节点向叶子节点扩展的时候优先遍历编号较小的节点.我还原出这课树特殊判定 根据bfs的顺序来建立这课树,用一个队列安排要 ...
- Chapter Schema
Chapter Schema Schema是XF的核心,每一个读写方法都有一个相关联的Schema.方法首先解析Schema,然后再根据Schema的配置的执行. 那Schema是什么呢?Schema ...
- XF 文档 - Element Framework Doc
配置篇 Chapter Configuration Schema篇 Chapter Schema 查询篇 Chapter Querying Data 数据更改及验证篇 Chapter Data Mod ...
- Coursera, Big Data 3, Integration and Processing (week 1/2/3)
This is the 3rd course in big data specification courses. Data model reivew 1, data model 的特点: Struc ...
- 《计算机科学基础》学习笔记_Part 1 Computer and Data
Technorati Tags: 计算机科学基础,读书笔记 Chapter 1. Introduction Ø 计算机:黑盒,Output Data=f(Input Data, Program) Ø ...
- MySQL Crash Course #06# Chapter 13. 14 GROUP BY. 子查询
索引 理解 GROUP BY 过滤数据 vs. 过滤分组 GROUP BY 与 ORDER BY 之不成文的规定 子查询 vs. 联表查询 相关子查询和不相关子查询. 增量构造复杂查询 Always ...
- (转)MapReduce Design Patterns(chapter 4 (part 1))(七)
Chapter 4. Data Organization Patterns 与前面章节的过滤器相比,本章是关于数据重组.个别记录的价值通常靠分区,分片,排序成倍增加.特别是在分布式系统中,因为这能提高 ...
- [转]Open Data Protocol (OData) Basic Tutorial
本文转自:http://www.odata.org/getting-started/basic-tutorial/ Basic Tutorial The Open Data Protocol (ODa ...
随机推荐
- eclipse luna maven搭建spring mvc
1. 环境配置 a) Java 1.7 b) Eclipse luna c) Maven3.2.5 d) Spring 4.1.4 2. ...
- 【性能诊断】十、性能问题综合分析(案例1,windbg、Network Monitor)
[问题描述]: 产品中某业务功能A,在进行"刷新"->选择制单->新增->切换其他行等一系列操作后,突然发生客户端不响应的现象. 经反复测 ...
- 【python】filter,map,reduce和lambda函数介绍
filter(function, iterable)map(function, iterable)reduce(function, sequence) filter将 function依次作用于ite ...
- 【转】ASP.NET MVC 的最佳实践
[This post is based on a document authored by Ben Grover (a senior developer at Microsoft). It is ou ...
- FIR系统的递归与非递归实现
首先,因为FIR的脉冲响应是有限长,所以总是可以非递归实现的: 其次,也可以用递归系统来实现它. 以滑动平均做例子,最直观的想法就是,每次来一个新的值,丢掉最老的,加上最新的: y[n]=y[n-1] ...
- bzoj1382: [Baltic2001]Mars Maps
Description 给出N个矩形,N<=10000.其坐标不超过10^9.求其面积并 Input 先给出一个数字N,代表有N个矩形. 接下来N行,每行四个数,代表矩形的坐标. Output ...
- chmod 权限777 是什么意思(Unix和Linux的各种操作系统下)
在Unix和Linux的各种操作系统下,每个文件(文件夹也被看作是文件)都按读.写.运行设定权限.例如我用ls -l命令列文件表时,得到如下输出:-rw-r--r-- 1 bu users 2254 ...
- Linux启动过程详解(转)
启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘 ...
- 华人曾与IBM抗衡! 盘点已远去的IT巨头(转)
[PConline资讯 ]从算盘到计算器,从大型机到个人PC,再到当今火热的移动终端和云计算,人类计算史已经走过了千年之久,现代IT计算领域也经过了百年浮沉.在世界工业领域,IT技术应该是诞生时间最短 ...
- [CSS]置换和非置换元素
转自:http://blog.doyoe.com 先进一个题外话 在面试一个 重构(各大公司的叫法可能不太一样)时,我喜欢从一个点开始问,然后一直延展下去成为一条线,甚至是一个面,直到问到不会的地方, ...