Welcome

首页 / 软件开发 / LINQ / Linq To Sql进阶系列(六)用object的动态查询与保存log篇

Linq To Sql进阶系列(六)用object的动态查询与保存log篇2011-08-20 博客园 Tom Song动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处。而Linq的推 出,是为了弥补编程中的 Data != Object 的问题。我们又该如何实现用object的动态查询呢?

1,用object的查询是什么?

我们可以简单的举这么一个例子。我们到公安局查找一个人。首先,我们会给出他的一些特征,比如 ,身高多少,年龄多少,性别,民族等。那么,我们把这个人的一些特征输入电脑。我们希望,电脑能 给我们返回这个人的信息。而实际上,有相同特征的人太多了,常常返回一个集合。那让我们把这个过 程抽象到程式里。我们需要new出来一个对象。这个对象包含了我们能知道的基本信息。而后,把这个对 象传给Linq To Sql,等待返回结果。

根据这些基本的需求,我们来定义下面的函数,为了实现这个函数对任何实体都是有用的,我们把它 定义为generic的。为了不破坏Linq To Sql延迟加载的规矩,我们把它的返回类型定义为IQueryable。 如下:

public IQueryable<TEntity> Find<TEntity>(TEntity obj) where TEntity : class

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

NorthwindDataContext db = new NorthwindDataContext();
//先new出一个对象
Customer c = new Customer();
//添入我们知道的最基本的信息,可以从ui获得
c.City = "London";
c.Phone = "23236133";
//call函数find返回结果
var q = db.Find<Customer>(c);

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);