抛弃EF,20分构建一个属于自己的ORM框架
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框架的更多相关文章
- 【转】抛弃EF,20分构建一个属于自己的ORM框架
链接:http://www.cnblogs.com/irenebbkiss/p/4157364.html
- Gora是一个类似Hibernate的ORM框架
Gora是一个类似Hibernate的ORM框架,但是不只是支持关系数据库,更重要支持NoSQL之类大数据的存储. 支持NoSQL之类大数据的存储 Apache Gora是一个开源的ORM(Objec ...
- 从零构建一个简单的 Python Web框架
为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...
- EF 太重,MyBatis 太轻,ORM 框架到底怎么选 ?
以 EF 为代表的基于 Linq 的 ORM 框架总是 很重. 他们的功能早已超出了一个 ORM 的范畴, ORM 是 Object Relational Mapping ,从名字上看,其初衷是将 数 ...
- Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架
本文首先介绍了什么是Apache Thrift,接着介绍了Thrift的安装部署及如何利用Thrift来实现一个简单的RPC应用,并简单的探究了一下Thrift的内部实现原理,最后给出一个基于Thri ...
- 1043 输出PATest (20 分)
题目:1043 输出PATest (20 分) 给定一个长度不超过 1 的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符.当然, ...
- PTA7-1 迷宫寻路 (20分)
7-1 迷宫寻路 (20分) 给定一个M行N列的迷宫图,其中 "0"表示可通路,"1"表示障碍物,无法通行.在迷宫中只允许在水平或上下四个方向的通路上行走,走过 ...
- 写一个ORM框架的第一步
新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...
- 写一个ORM框架的第一步(Apache Commons DbUtils)
新一次的内部提升开始了,如果您想写一个框架从Apache Commons DbUtils开始学习是一种不错的选择,我们先学习应用这个小“框架”再把源代码理解,然后写一个属于自己的ORM框架不是梦. 一 ...
随机推荐
- 欧拉工程第56题:Powerful digit sum
题目链接 Java程序 package projecteuler51to60; import java.math.BigInteger; import java.util.Iterator; im ...
- sin=in.readLine();
import java.io.*; public class LineIO{ public static void main(String[] args) { String sin,inputStri ...
- 读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots
读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots 以下为异常详细信息: Exception in thread &q ...
- centos使用fuse挂载NTFS
FUSE:用户空间文件系统(Filesystem in Userspace),是Linux 中用于挂载某些网络空间,如SSH,到本地文件系统的模块.如果装的是双系统,centOS并不支持ntfs分区, ...
- ASP.NET 在IIS7.5下自定义404错误页面的方法
.net 4.0 本机调试时一切正常,配置如下 <customErrors redirectMode="ResponseRewrite" mode="On& ...
- Xlib: connection to ":0.0" refused by server Xlib: No protocol specified解决方案
Xlib: connection to ":0.0" refused by server Xlib: No protocol specified 解决办法: 1. 退出oracl ...
- jquery 计算输入的文本的utf-8字节长度
jquery-2.1.1.min.js /*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license ...
- ubuntu下如何查看用户登录及系统授权相关信息【转】
转自:http://www.tuicool.com/articles/ia67Bj 如何在ubuntu下查看相关用户登录历史,进行系统的日志跟踪和分析,以便发现系统登录问题,进行安全策略防护呢?ubu ...
- 2-Medium下的MultipleCommandAssembly
1.首先创建一个控制台项目 2.添加引用[红色的都是将项目添加为引用,其中蓝色的log4net是直接从源代码下的Reference文件夹下引用的dll] 3.写代码 1)首先将config配置好[ht ...
- javascirpt历史澄清误解基本概念特点编程语言web2.0网页javascript - javascirpt知识大全
目录1历史 2澄清误解 3基本概念 4特点 5与Java的不同 6开发工具 历史 大概在1992年,一家称作Nombas的公司开始开发一种叫做C减减(C-minus-minus,简称Cmm)的嵌入式脚 ...