场景

最近对爬虫的数据库架构做调整,需要将数据迁移到MongoDB上去,需要重新实现一个针对MongoDB的Dao泛型类,好吧,动手开工,当实现删除操作的时候问题来了。

我们的删除操作定义如下:void Delete(TEntity entity)。TEntity是我们的泛型类。

而MongoDB官方驱动自带的删除操作是这样的:


1
2
3
// 假设数据模型为已定义的Article
var query = Query<Article>.EQ(t => t.Id, id);
coll.Remove(query);

Dao操作的接口是不能修改的,这就要求我们必须实现以下操作:

  1. 获取entity的Id值
  2. 构造lambda表达式用于获取Id属性

实现

对于第1个好办,直接通过反射拿就可以了,至于第2个构造lambda表达式却不知该如何下手了。

在网上查资料了解到C# Lambda表达式树允许我们像处理数据(比如读取,修改)一样来处理Lambda表达式。。这就有方向了,研究了一下表达式树的相关知识,历经坎坷终于将其实现。

我用到的lambda表达式比较简单,也容易构造,代码中看注释应该就明白了,代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// <summary>
/// 因为使用的Mongodb,每个数据模型必定包含Id属性,通过Id属性来删除实体
/// </summary>
/// <param name="entity"></param>
public void Delete(TEntity entity)
{
var coll = _db.GetCollection<TEntity>(typeof(TEntity).Name);
if (entity == null)
{
return;
}
ObjectId id = (ObjectId)typeof(TEntity).GetProperty("Id").GetValue(entity, null); // 通过表达式树构造lambda表达式{t => t.Id}
// 构造调用目标t
var target = Expression.Parameter(typeof(TEntity), "t");
// 构造对t的属性Id的表达式
MemberExpression bodyExp = Expression.Property(
target,
"Id"); // 构造完整的lambda表达式
Expression<Func<TEntity, ObjectId>> selector =
Expression.Lambda<Func<TEntity, ObjectId>>(bodyExp, new [] { target }); // 使用泛型前的语句: Query<Article>.EQ(t => t.Id, id);
var query = Query<TEntity>.EQ(selector, id);
coll.Remove(query);
}

参考资料

  1. C# Lambda表达式树浅谈
  2. C#教程:lambda表达式转换成表达式树

用到的工具

之前都是直接使用lambda表示,而且用的还很Happy,今天遇到的问题,让我很傻眼,基础还得巩固啊。今天也是第一次调试lambda表达式,用到了Expression Tree Visualizer for VS 2010这个小工具。在项目调试过程中可以比较直观的查看编译好的lambda表达式。

安装和使用方法,请参见:在Visual Studio 2010设置Expression Tree Visualizer

C#在泛型类中,通过表达式树构造lambda表达式的更多相关文章

  1. lintcode :前序遍历和中序遍历树构造二叉树

    解题 前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树: 2 / \ 1 3 注意 你可以假设树中不存 ...

  2. LintCode-73.前序遍历和中序遍历树构造二叉树

    前序遍历和中序遍历树构造二叉树 根据前序遍历和中序遍历树构造二叉树. 注意事项 你可以假设树中不存在相同数值的节点 样例 给出中序遍历:[1,2,3]和前序遍历:[2,1,3]. 返回如下的树:    ...

  3. [leetcode/lintcode 题解] 前序遍历和中序遍历树构造二叉树

    [题目描述] 根据前序遍历和中序遍历树构造二叉树. 在线评测地址: https://www.jiuzhang.com/solution/construct-binary-tree-from-preor ...

  4. .NET技术-6.0. Expression 表达式树 生成 Lambda

    .NET技术-6.0. Expression 表达式树 生成 Lambda public static event Func<Student, bool> myevent; public ...

  5. 构造Lambda表达式

    /// <summary> /// 构造Lambda表达式 /// </summary> /// <typeparam name="T">< ...

  6. C++11中新特性之:lambda 表达式

    首先摆出Lambda表达式语法 lambda-expression: lambda-introducer lambda-declaratoropt compound-statementlambda-i ...

  7. C++11 中function和bind以及lambda 表达式的用法

    关于std::function 的用法:  其实就可以理解成函数指针 1. 保存自由函数 void printA(int a) { cout<<a<<endl; } std:: ...

  8. C#中的委托,匿名方法和Lambda表达式

    简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=.答案是6个Firs ...

  9. (转)C#中的委托,匿名方法和Lambda表达式

    简介 在.NET中,委托,匿名方法和Lambda表达式很容易发生混淆.我想下面的代码能证实这点.下面哪一个First会被编译?哪一个会返回我们需要的结果?即Customer.ID=5.答案是6个Fir ...

随机推荐

  1. [待解决] sudo unable to resolve host

    怪哉怪哉, 大debian突然就出现了这个问题 , 问题的现象是只要使用 sudo 执行命令就会出现 sudo unable to resolve host </etc/hostname中的内容 ...

  2. sql语句中where和having的区别

    WHERE语句在GROUPBY语句之前:SQL会在分组之前计算WHERE语句. HAVING语句在GROUPBY语句之后:SQL会在分组之后计算HAVING语句.

  3. php导出word格式数据的代码

    <?php /** * 生成word文档的类 * by www.jbxue.com */ class word {          function start()     {         ...

  4. nginx负载均衡的实现

    将一台nginx主机当作前端负载均衡服务器,后面通过交换机链接多台web服务器,提供html和php的web界面服务.通过配置前端负载均衡服务器,可以实现将html界面和php界面的分开访问,即htm ...

  5. python 去除字符串中连续的空格,并使用其他的分隔符替代连续的空格

    例:1: filt函数用法及匿名函数lamda用法,详见http://www.cnblogs.com/apple2016/p/5657698.html join()用法详见http://www.cnb ...

  6. 人工智能范畴及深度学习主流框架,IBM Watson认知计算领域IntelligentBehavior介绍

    人工智能范畴及深度学习主流框架,IBM Watson认知计算领域IntelligentBehavior介绍 工业机器人,家用机器人这些只是人工智能的一个细分应用而已.图像识别,语音识别,推荐算法,NL ...

  7. java几道简单的面试题目

    1.   请问以下程序会输出什么? public   class   Test   {  public   static   void   main(String[]   args)   {  Par ...

  8. laravel数据库的创建和迁移

    数据库建立及迁移 Laravel 5 把数据库配置的地方改到了 `learnlaravel5/.env`,打开这个文件,编辑下面四项,修改为正确的信息: ? 1 2 3 4 5 6 7 DB_HOST ...

  9. Makefile学习之make 的运行【转】

    转自:http://blog.csdn.net/suzilong11/article/details/7852830 —————— 一般来说,最简单的就是直接在命令行下输入make命令,make命令会 ...

  10. Java中类方法与实例方法的区别

    实例方法可以对当前对象的实例变量进行操作,也可以对类变量进行操作,但类方法不能访问实例变量.实例方法必须由实例对象来调用,而类方法除了可由实例对象调用外,还可以由类名直接调用. 另外,在类方法中不能使 ...