Poiuyt_cyc

博客园首页新随笔联系订阅管理随笔 - 11  文章 - 0  评论 - 111

抛弃EF,20分构建一个属于自己的ORM框架

相信EF大家都不陌生了,因为数据库表跟程序实体是一一对应的原因,我们能够通过lambda这种函数式的编程方式进行操作数据库,感觉非常清晰明了。与我们直接写SQL相比,lambda是强类型,拥有更好的扩展性,伸缩性,而且编程更加的方便,快捷。。下面我们就基于Expression和lambda来与大家构建一个属于自己的ORM框架。

思路的话很简单,就是将lambda转换成我们对应的数据库所需的查询条件,然后执行查询,再将结果以反射的方式封装成List<T>返回出去。

Expression

大家使用EF的时候多多少少会留意到有Expression这个东西。特别是查询时会看到要你传入Expression<Func<T,bool>>这样类型的参数,它又和Func<T,bool>有什么比同呢?

Expression<Func<T,bool>>是表达式树,我们可以通过它来分析我们的委托中的函数。当调用Compile方法后就会变成委托,才能执行。

Func<T,bool>只是一个普通的委托。

例如我们现在有个实体类Staff

public class Staff

{

public string Name { get; set; }

public int Age { get; set; }

public string Code { get; set; }

public DateTime? Birthday { get; set; }

public bool Deletion { get; set; }

}

我们还有一个这样的方法

class Program

{

static void Main(string[] args)

{

FindAs<Staff>(x => x.Code == "张三" && x.Name.Contains("张"));

}

public static List<T> FindAs<T>(Expression<Func<T, bool>> func)

{

//将func转换成对应数据库的查询条件,然后执行查询

return null;//将结果返回

}

}

我们希望通过 FindAs<Staff>(x => x.Age <50 && x.Name.Contains("张")); 就能查询出Staff表中Age<50并且Name包含有“张”字的人的信息。而生成的sql语句应该是select * from staff where Age<50 and Name like '%张%'。现在我们就来分析下这个func

从上面的图我们可以看到当前的Expression是一个lambda表达式,我们点开它的body看看。

我们可以看到body里分为左边和右边,还有NodeType。和我们的lambda对比下看看'x => x.Code =="张三" && x.Name.Contains("张")'是不是找到点灵感了?我们再继续把左边和右边拆开看看。

可以看到我们需要的信息都有了,看来转换成SQL已经不是什么难事了,动手开搞了。

class Program

{

static void Main(string[] args)

{

FindAs<Staff>(x => x.Code == "张三" && x.Name.Contains("张"));

FindAs<Staff>(x => x.Age <= 12 && x.Name.Contains("张"));

Console.ReadKey();

}

public static List<T> FindAs<T>(Expression<Func<T, bool>> func)

{

BinaryExpression Binary = func.Body as BinaryExpression;

string left = ResovleFunc(Binary.Left);

string right = ResovleLinqToObject(Binary.Right);

string oper = GetOperator(Binary.NodeType);

string sql = string.Format("select * from {0} where {1}", typeof(T).Name, left + oper + right);

Console.WriteLine(sql);

return null;//将结果返回

}

//解析一般的条件,例如x=>x.name==xxxx   x.age==xxx

public static string ResovleFunc(Expression express)

{

var inner = express as BinaryExpression;

string Name = (inner.Left as MemberExpression).Member.Name;

object Value = (inner.Right as ConstantExpression).Value;

var Operator = GetOperator(inner.NodeType);

string Result = string.Format("({0} {1} '{2}')", Name, Operator, Value);

return Result;

}

//解析linq to object这类扩展方法

public static string ResovleLinqToObject(Expression expression)

{

var MethodCall = expression as MethodCallExpression;

var MethodName = MethodCall.Method.Name;

if (MethodName == "Contains")

{

object Temp_Vale = (MethodCall.Arguments[0] as ConstantExpression).Value;

string Value = string.Format("%{0}%", Temp_Vale);

string Name = (MethodCall.Object as MemberExpression).Member.Name;

string Result = string.Format("{0} like '{1}'", Name, Value);

return Result;

}

return null;

}

public static string GetOperator(ExpressionType expressiontype)

{

switch (expressiontype)

{

case ExpressionType.And:

return "and";

case ExpressionType.AndAlso:

return "and";

case ExpressionType.Or:

return "or";

case ExpressionType.OrElse:

return "or";

case ExpressionType.Equal:

return "=";

抛弃EF,20分构建一个属于自己的ORM框架的更多相关文章

  1. 【转】抛弃EF,20分构建一个属于自己的ORM框架

    链接:http://www.cnblogs.com/irenebbkiss/p/4157364.html

  2. Gora是一个类似Hibernate的ORM框架

    Gora是一个类似Hibernate的ORM框架,但是不只是支持关系数据库,更重要支持NoSQL之类大数据的存储. 支持NoSQL之类大数据的存储 Apache Gora是一个开源的ORM(Objec ...

  3. 从零构建一个简单的 Python Web框架

    为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...

  4. EF 太重,MyBatis 太轻,ORM 框架到底怎么选 ?

    以 EF 为代表的基于 Linq 的 ORM 框架总是 很重. 他们的功能早已超出了一个 ORM 的范畴, ORM 是 Object Relational Mapping ,从名字上看,其初衷是将 数 ...

  5. Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架

    本文首先介绍了什么是Apache Thrift,接着介绍了Thrift的安装部署及如何利用Thrift来实现一个简单的RPC应用,并简单的探究了一下Thrift的内部实现原理,最后给出一个基于Thri ...

  6. 1043 输出PATest (20 分)

    题目:1043 输出PATest (20 分) 给定一个长度不超过 1 的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符.当然, ...

  7. PTA7-1 迷宫寻路 (20分)

    7-1 迷宫寻路 (20分) 给定一个M行N列的迷宫图,其中 "0"表示可通路,"1"表示障碍物,无法通行.在迷宫中只允许在水平或上下四个方向的通路上行走,走过 ...

  8. 写一个ORM框架的第一步

    新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...

  9. 写一个ORM框架的第一步(Apache Commons DbUtils)

    新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...

随机推荐

  1. QT5.3无法自动调用incomingConnection函数的问题(4.7没有这个问题)

    最近将qt4.7的一个工程移到5.3,遇到了几个麻烦事,主要是这个incomingConnection监听后无法自动调用的问题,在4.7上是完全没有问题的,到了5.3就不行,网上也查了下,网友们都是放 ...

  2. Delphi对象变成Windows控件的前世今生(关键是设置句柄和回调函数)goodx

    ----------------------------------------------------------------------第一步,准备工作:预定义一个全局Win控件变量,以及一个精简 ...

  3. Adb connection Error:远程主机强迫关闭了一个现有的连接 解决方法

    用真机调试程序的时候,eclipse 的 Console 总是出现如下的错误"Adb connection Error:远程主机强迫关闭了一个现有的连接". 问题出现的原因:这是 ...

  4. SQL Server ->> 分区表上创建唯一分区索引

    今天在读<Oracle高级SQL编程>这本书的时候,在关于Oracle的全局索引的章节里面有一段讲到如果对一张分区表创建一条唯一索引,而索引本身也是分区的,那就必须把分区列也加入到索引列表 ...

  5. Wordnet 与 Hownet 比较

    近年来,随着计算机本身以及信息高速公路的飞速发展,人们开始更加重视语义的研究.各国都致力于可用于自然语言处理的大规模语义词典或大规模知识库的建设.例如:普林斯顿大学的英语Wordnet,微软的Mind ...

  6. JAVASCRIPT和JQUERY判断浏览器信息总汇(备忘)

    <script type="text/javascript">        //jquery判断浏览器信息        $(function(){          ...

  7. Java @override报错的解决方法

    在eclipse中导入工程后@Overide报错 到入工程后,所有的@Override都报如下错误: Multiple markers at this line - The method getCou ...

  8. poj - 3723 Conscription(最大权森林)

    http://poj.org/problem?id=3723 windy需要挑选N各女孩,和M各男孩作为士兵,但是雇佣每个人都需要支付10000元的费用,如果男孩x和女孩y存在亲密度为d的关系,只要他 ...

  9. 运行所有sdk目录下的示例,查看它们的功能,方便以后查寻

    运行所有sdk目录下的示例,查看它们的功能,方便以后查寻

  10. 无锁编程(四) - CAS与ABA问题

    CAS 一般采用原子级的read-modify-write原语来实现Lock-Free算法,其中LL和SC是Lock-Free理论研究领域的理想原语,但实现这些原语需要CPU指令的支持,非常遗憾的是目 ...