Linq To Sql进阶系列(六)用object的动态查询与保存log篇
动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处。而Linq的推出,是为了弥补编程中的 Data != Object 的问题。我们又该如何实现用object的动态查询呢?
1,用object的查询是什么?
我们可以简单的举这么一个例子。我们到公安局查找一个人。首先,我们会给出他的一些特征,比如,身高多少,年龄多少,性别,民族等。那么,我们把这个人的一些特征输入电脑。我们希望,电脑能给我们返回这个人的信息。而实际上,有相同特征的人太多了,常常返回一个集合。那让我们把这个过程抽象到程式里。我们需要new出来一个对象。这个对象包含了我们能知道的基本信息。而后,把这个对象传给Linq To Sql,等待返回结果。
根据这些基本的需求,我们来定义下面的函数,为了实现这个函数对任何实体都是有用的,我们把它定义为generic的。为了不破坏Linq To Sql延迟加载的规矩,我们把它的返回类型定义为IQueryable。如下:

思路出来了,先new出来一个对象,然后把对象传给这个函数,我们渴望它能返回与这个对象匹配的结果集。为了让它和DataContext有关系,我们把这个函数放到DataContext的partial类里。鼠标右击Linq To Sql文件,选择view code,这个时候,vs会为你创造一个DataContext的partial类,其扩展名比影射文件少了中间的desiger。大家要注意,你如果想自己修改影射文件,请放到这个文件里。这样当影射code被刷新时,才不会冲掉你自己的修改。先大体描述下我们的思路。








2,原理
Linq To Sql支持用户动态生成lambda表达式。本文中所实现的方法,正是反射加lambda动态表达式。我们先来看如何动态生成lambda表达式。在Linq 中,lambda表达式会首先转化为Expression Tree,本文并不详解Expression Tree。Expression Tree是lambda表达式从code的形式转化为data的结果,是一种更高效的在内存中的数据结构。比如:
Func<int,int> f = x => x + 1; // Code
Expression<Func<int,int>> e = x => x + 1; // Data
第二个,其实也就是第一个转化后的形式。那好了,有了这个前提,我们就可以动态构造这个Expression Tree了。
// 先构造了一个ParameterExpression对象,这里的c,就是Lambda表达中的参数。(c=>)
ParameterExpression param = Expression.Parameter(typeof(TEntity), "c");
//构造表达式的右边,值的一边
Expression right = Expression.Constant(p.GetValue(obj, null));
//构造表达式的左边,property一端。
Expression left = Expression.Property(param, p.Name);
//生成筛选表达式。即c.CustomerID == "Tom"
Expression filter = Expression.Equal(left, right);
//生成完整的Lambda表达式。
Expression<Func<TEntity, bool>> pred = Expression.Lambda<Func<TEntity, bool>>(filter, param);
//在这里,我们使用的是and条件。
query = query.Where(pred);
3,反射在本方法中的作用
因为我们采用了模板,也就是说,我们并不知道传进来的对象会有那些property,那反射在这里就提供一个很好的方法。我们可以通过反射去遍历每一个property,只有判断出该property的值不为null时,才将其视为条件。该函数完整的代码如下:


































4,测试用例及反思
我们用下面的例子来测试下这个函数





其生成的sql语句为:





我们可以看到,其sql语句中,只有city和phone两个条件。并且他们之间是and的关系。我们最开始的设想实现了,但是,它是完美的吗?如果是or条件该怎么办呢?更多的时候,我们是在用模糊查询,那又该怎么办呢?这个问题,就留于下篇。
最后,介绍一种写log的方法。stream流使用static为避免多个datacontext的同时在使用log.txt文件。


































在dispose函数里,把输出流flush。使用时,如下
using(northwind db = new norhwind(true))
{
//do something......
}
好,就先讲到这里。
Linq To Sql进阶系列(六)用object的动态查询与保存log篇的更多相关文章
- SQL进阶系列之6用关联子查询比较行与行
写在前面 使用SQL对同一行数据进行列间的比较很简单,只需要在WHERE子句里写上比较条件就可以了,对于不同行数据进行列间比较需要使用自关联子查询. 增长.减少.维持现状 需要用到行间比较的经典场景是 ...
- Bing Maps进阶系列六:使用Silverlight剪切(Clip)特性实现Bing Maps的迷你小地图
Bing Maps进阶系列六:使用Silverlight剪切(Clip)特性实现Bing Maps的迷你小地图 Bing Maps Silverlight Control虽然为我们提供了简洁.方面的开 ...
- .NET深入实战系列—Linq to Sql进阶
最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方. 本文全部代码基于:UserInfo与Class两个表,其中Cla ...
- SQL进阶系列之7用SQL进行集合运算
写在前面 集合论是SQL语言的根基,因为这种特性,SQL也被称为面向集合语言 导入篇:集合运算的几个注意事项 注意事项1:SQL能操作具有重复行的集合(multiset.bag),可以通过可选项ALL ...
- SQL进阶系列之12SQL编程方法
写在前面 KISS -- keep it sweet and simple 表的设计 注意命名的意义 英文字母 + 阿拉伯数字 + 下划线"_" 属性和列 编程的方针 写注释 注意 ...
- SQL进阶系列之10HAVING子句又回来了
写在前面 HAVING子句的处理对象是集合而不是记录 各队,全队点名 --各队,全体点名! CREATE TABLE Teams (member CHAR(12) NOT NULL PRIMARY K ...
- SQL进阶系列之11让SQL飞起来
写在前面 SQL的性能优化是数据库使用者必须面对的重要问题,本节侧重SQL写法上的优化,SQL的性能同时还受到具体数据库的功能特点影响,这些不在本节讨论范围之内 使用高效的查询 参数是子查询时,使用E ...
- SQL进阶系列之9用SQL处理数列
写在前面 关系模型的数据结构里,并没有顺序的概念,但SQL处理有序集合也有坚实的理论基础 生成连续编号 --生成连续编号 CREATE TABLE Digits (digit INTEGER PRIM ...
- SQL进阶系列之8EXISTS谓词的用法
写在前面 支撑SQL和关系数据库的基础理论:数学领域的集合论和逻辑学标准体系的谓词逻辑 理论篇 什么是谓词?谓词是返回值为真值(true false unknown)的函数 关系数据库里,每一个行数据 ...
随机推荐
- 【LeetCode】Permutations(全排列)
这道题是LeetCode里的第46道题. 题目要求: 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3 ...
- ubuntu 终端查看图片(eog)
远程登陆服务器的话,是没有办法直接查看图片的,这时我们需要进入图片所在目录,然后通过终端命令查看图片. 想要查看图片,需要通过ssh -X登陆,然后在终端输入命令: eog 图片名
- .net提高文章
文章:.NET程序性能的基本要领 文章:你的字典里有多少元素? 文章:快速自检电脑是否被黑客入侵过(Windows版) 文章:关于DNS,你应该知道这些
- HDU——1045Fire Net(最大匹配)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- docker-nginx-标记一下
拉取nginx镜像 然后启动容器: docker run -p : --name mynginx -d -v $PWD/nginx.conf:/etc/nginx/conf.d/default.con ...
- golang测试框架--smartystreets/goconvey
视频教程和配套博客:goconvey - 课时 1:优雅的单元测试 Go 语言虽然自带单元测试功能,在 GoConvey 诞生之前也出现了许多第三方辅助库.但没有一个辅助库能够像 GoConvey 这 ...
- Linux 下 GCC 编译共享库控制导出函数的方法
通过一些实际项目的开发,发现这样一个现象,在 Windows 下可以通过指定 __declspec(dllexport) 定义来控制 DLL(动态链接库)中哪些函数可以导出,暴露给其他程序链接使用,哪 ...
- shell高级-----初识sed和gawk
sed编辑器 sed说明 sed是Linux下一款功能强大的非交互流式文本编辑器,可以对文本文件进行增.删.改.查等操作,支持按行.按字段.按正则匹配文本内容,灵活方便,特别适合于大文件的编辑. 替换 ...
- idea修改变量及其引用
idea 修改某一变量及其引用 选中变量 shift+f6(shift+fn+f6), ctrl+R的当前页面全局替换, ctrl+shift+R 项目中的全局替换
- MFC中的几种播放声音的方法
一.播放声音文件的简单方法 在VC++ 中的多媒体动态连接库中提供了一组与音频设备有关的函数.利用这些函数可以方便地播放声音.最简单的播放声音方法就是直接调用VC++中提供的声音播放函 数BOOL s ...