1,用object的查询是什么?
我们可以简单的举这么一个例子。我们到公安局查找一个人。首先,我们会给出他的一些特征,比如,身高多少,年龄多少,性别,民族等。那么,我们把这个人的一些特征输入电脑。我们希望,电脑能给我们返回这个人的信息。而实际上,有相同特征的人太多了,常常返回一个集合。那让我们把这个过程抽象到程式里。我们需要new出来一个对象。这个对象包含了我们能知道的基本信息。而后,把这个对象传给Linq To Sql,等待返回结果。
根据这些基本的需求,我们来定义下面的函数,为了实现这个函数对任何实体都是有用的,我们把它定义为generic的。为了不破坏Linq To Sql延迟加载的规矩,我们把它的返回类型定义为IQueryable。如下:
public IQueryable<TEntity> Find<TEntity>(TEntity obj) where TEntity : class
NorthwindDataContext db = new NorthwindDataContext(); //先new出一个对象 Customer c = new Customer(); //添入我们知道的最基本的信息,可以从ui获得 c.City = "London"; c.Phone = "23236133"; //call函数find返回结果 var q = db.Find<Customer>(c);
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
// 先构造了一个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);
因为我们采用了模板,也就是说,我们并不知道传进来的对象会有那些property,那反射在这里就提供一个很好的方法。我们可以通过反射去遍历每一个property,只有判断出该property的值不为null时,才将其视为条件。该函数完整的代码如下:
public IQueryable<TEntity> Find<TEntity>(TEntity obj) where TEntity : class { //获得所有property的信息 PropertyInfo[] properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); //构造初始的query IQueryable<TEntity> query = this.GetTable<TEntity>().AsQueryable<TEntity>(); //遍历每个property foreach (PropertyInfo p in properties) { if (p != null) { Type t = p.PropertyType; //加入object,Binary,和XDocument, 支持sql_variant,imager 和xml等的影射。 if (t.IsValueType || t == typeof(string) || t == typeof(System.Byte[]) || t == typeof(object) || t == typeof(System.Xml.Linq.XDocument) || t == typeof(System.Data.Linq.Binary)) { //如果不为null才算做条件 if ( p.GetValue(obj, null) != null) { ParameterExpression param = Expression.Parameter(typeof(TEntity), "c"); Expression right = Expression.Constant(p.GetValue(obj, null)); Expression left = Expression.Property(param, p.Name); Expression filter = Expression.Equal(left,right); Expression<Func<TEntity, bool>> pred = Expression.Lambda<Func<TEntity, bool>>(filter, param); query = query.Where(pred); } } } } return query; }
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/