记得去年初就开始关注Entity Framework,那时只是简单测试了一下,发现较之Nhibernate不太成熟。当时的EF主要表驱动方式开发,过度依赖edm文件,并且数据层耦合了模型层,让一些MVC分层用户痛苦不堪。微软从Oxite1项目发展到Oxite2也在这个DAL与MODEL的理不清的关系上做过徘徊,只好在EDM的基础上直接实现BLL。由于EntityObject模型与ObjectContext耦合,在N层架构构中EntityObject直接提供给客户端使用的话,那ObjectContext在客户端也会被调用,因此这个时候只能通过DTO对象的方式解决,而毕竟大部分EntityObject是可以直接传递使用的,而不是一定通过DTO传递。
     我们看看现在的EF4.0和EF4.1有哪些进步,先来解释一些名词
EDM文件
    EDM是实体数据关系映射的XML文件,不同于Nhibernate每个对象单独映射了一个XML文件。EDM主要有三部分构成CSDL,SSDL,MSL。CSDL表面的是实体数据模型结构,SSDL表示对应的数据存储的架构,CSDL实体与SSDL数据结构的关系通过MSL映射实现。EDM是通过ADO.NET 实体数据模型生成的
生成EDM文件的方式有两种,一种基于是数据库,一种是创建空EDM模型。前者就是后面要提到的DataBase First方式,后者是Model First方式。
针对创建好的EDM模型最终要生成代码,生成代码的工具不同,生成的代码也不同。看看下面几种生成方式,都于基于EDM模型生成的。
ADO.NET 实体数据模型   最初EF的方式,实体模型EntityObject与ObjectContext耦合在一起,不适合分层使用。
ADO.NET 自跟踪实体生成器  分离生成基于POCO的SelfTrackingEnityObject模型和ObjectContext (这种方试即使设置了延迟加载也无法加载关联导航属性,要在使用时手动加载)
ADO.NET DbContext Generator 分离生成纯POCO模型和轻型DbContext。DbContext较之ObjectContext比较简洁,并且POCO可以充分利用。
这就是我为什么选ADO.NET DbContext Generator 的原因,我们再看看EF框架的划分的模式
  1. DataBase First
  2. Model First
  3. Code First
DataBase First   传统的表驱动方式创建edm,然后通过edm生成模型和数据层代码。除生成实体模型和自跟踪实现模型,还支持生成纯POCO模型和轻型DbContext。
Model First  先创建EDM模型,再生成DDL数据库脚本和模型和数据层代码。除生成实体模型和自跟踪实现模型,支持生成纯POCO模型和轻型DbContext。
Code First 手动创建POCO模型,数据层DbContext及映射关系,通过Database.SetInitializer生成数据库,这种方式较灵活,但是代码工作较多。
虽然Code First灵活,但是我们不可能手工去写大量的POCO类和映射关系。如果借助其它ORM工具生成Code First的需要POCO类,为什么试试Model First生成Code First需要的代码呢?
本篇选择基于Model First方式+通过ADO.NET DbContext Generator生成基于Code First方式代码 ,是不是有点概念混乱?但是这种方式基本上和Nhibernate是一致的,而Nhibernate又有着广泛的项目基础。
Model First方式  主要解决构建模型和EDM映射文件工作
ADO.NET DbContext Generator 基于EDM文件生成POCO模型,DbContext代码以及DDL数据库脚本。因为Code First你要自己实现POCO,DbContext的代码,这部分工作如果不借助工具实现代码量还是很大的。做项目不可能像写个Demo用简单的几个类演示一下就完了,总不能为了演示而学习,最终还是要提高工作效率。这也是为什么我觉得EF已经成熟了决定用于项目的原因。
 
下面就把这个过程简单的走一遍:
1.首先创建项目,类库EF.Model,EF.DAL,EF.BLL,控制台EF.Demo。
在类库EF.DAL中创建空EDM模型 (为什么要在EF.DAL创建EDM,而不是EF.Model中创建,后面会说明),打开空的EDM模型,我们构建几个实体对象,并映射各个实体间的关系。
EDM视图如下
 
右键属性选择根据模型生成数据库-> 生成DemoDB.edmx.sql脚本->打开脚本 右键执行SQL 生成到数据库
 
2.添加代码生成
完成我们的对象设计后,右键EMD属性->添加代码生成项...->选择ADO.NET DbContext Generator生成器 ,这个时候EDMX就变成空模板了,属性生成代码策略被关闭
完成后,会自动生成两个tt文件,一个DemoDB.Context.tt (DbContext),一个DemoDB.tt (POCO)
 
 我们将DemoDB.edmx和Demo.tt 两个文件COPY到EF.Model中,并且删除掉EF.DAL中的这两个文件。由于DemoDB.edmx和Demo.tt 两个文件是在EF.DAL创建的,所以移到EF.Model中他们的命名空间还是EF.DAL。不用担心,我们在EF.Model中打开DemoDB.edmx和Demo.tt两个模板文件,点击保存后,模板会自动修改命名空间为EF.Model。注意了EF.DAL中的DemoDB.Context.tt模板不要打开保存,否则DbContext的代码会丢失。 这样我们完成了Model和DAL代码的分离工作了。
(DbContext 是EF4.1内容, 另外在VS解决方案的工具里有扩展管理器可直接下载最新的VS扩展插件,通过Library Package Manager的控制台直接添加引用)
 如果对象修改了,我们只要再保存EDM模板就可以及时更新DemoDB.tt中的对象。而DAL层基本上不需要修改。
 
3. EF.DAL创建通用数据操作类库(仿Nhibernate)
IRepository接口:(IOC注入)

RepositoryBase 抽象基类实现
IBlogCategoryRepository 接口(IOC注入)
 BlogArticleRepository实现
 
看看后面两个具体数据操作类的代码极其简单,这就是EF4.0 之后的泛型的优点 ,可以使代码尽量的简洁。
 
4.EF.BLL层简单的实现一下业务
BlogCategoryService 实现关联表操作(添加一个BlogCategory分类,并且在这个分类下增加一个BlogArticle文章)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EF.DAL;
using EF.Model; namespace EF.BLL
{
public class BlogCategoryService
{
IRepository<BlogCategory> repositoryCategory;
IRepository<BlogArticle> repositoryArticle;
public BlogCategoryService(IRepository<BlogCategory> repositoryCategory,IRepository<BlogArticle> repositoryArticle)
{
this.repositoryCategory = repositoryCategory;
this.repositoryArticle = repositoryArticle;
} public BlogCategoryService()
{
this.repositoryCategory = new BlogCategoryRepository();
this.repositoryArticle = new BlogArticleRepository();
} public BlogCategory CreateBlogCategory()
{
return repositoryCategory.Create();
} public BlogArticle CreateBlogArticle()
{
return repositoryArticle.Create();
} public BlogCategory Insert(BlogCategory entity)
{
return repositoryCategory.Insert(entity);
} public BlogCategory Update(BlogCategory entity)
{
return repositoryCategory.Update(entity);
} public void Delete(BlogCategory entity)
{
repositoryCategory.Delete(entity);
}
}
}
 
5.EF.Model测试导航属性关联操作(同时往两张表插入记录)

 
6.结果
 
通过Model First的方式+ADO.NET DbContext Generator生成器 实现Code First方式业务(EDMX通过DbContext构造注入其中),到达Hibernate的效果。EDMX相当于Hibernate 对象模型XML映射文件,POCO相当于Hibernate对象模型(virtual实现关联导航加载),DbContext通过泛型构建IRepository数据操作类。之前看到相关测试,微软的EF ADO.NET 测试效率高出Hibernate 30%左右,不知道是不是真的-_-|||。
 
另外提一点 DbContext 可以转换为ObjectContext,用Refletor反编译看到是通过一个中间InternalContext实现的
实现代码: ObjectContext  context =  ((IObjectContextAdapter) DbContext).ObjectContext;
如果不想直接加载导航属性数据,你可以在DbContext的构造函数禁用延迟加载。
 
 EF提供了强大的查询框架,有时间再写篇探讨自定义查询的,至此,不必犹豫不决了,可以在项目中实践一下。
如果表设计DateTime字段不允许为空,EF执行SaveChanges会出错,建议使用DateTime2类型解决(SQL2008以后版本)
 
 

Entity Framework之犹豫不决的更多相关文章

  1. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库

    在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...

  2. Entity Framework Core 1.1 升级通告

    原文地址:https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-entity-framework-core-1-1/ 翻译:杨晓东 ...

  3. Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制

    将通用的序列号生成器库 从SQL Server迁移到Mysql 遇到的一个问题,就是TimeStamp/RowVersion并发控制类型在非Microsoft SQL Server数据库中的实现.SQ ...

  4. 采用MiniProfiler监控EF与.NET MVC项目(Entity Framework 延伸系列1)

    前言 Entity Framework 延伸系列目录 今天来说说EF与MVC项目的性能检测和监控 首先,先介绍一下今天我们使用的工具吧. MiniProfiler~ 这个东西的介绍如下: MVC Mi ...

  5. 来,给Entity Framework热热身

    先来看一下Entity Framework缓慢的初始化速度给我们更新程序带来的一种痛苦. 我们手动更新程序时通常的操作步骤如下: 1)把Web服务器从负载均衡中摘下来 2)更新程序 3)预热(发出一个 ...

  6. 采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)

    前言 Entity Framework 延伸系列目录 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这 ...

  7. Entity Framework教程(第二版)

    源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...

  8. Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新

    因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...

  9. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第一章:创建基本的MVC Web站点

    在这一章中,我们将学习如何使用基架快速搭建和运行一个简单的Microsoft ASP.NET MVC Web站点.在我们马上投入学习和编码之前,我们首先了解一些有关ASP.NET MVC和Entity ...

随机推荐

  1. Python3基础 str partition 以参数字符串切分字符串,只切分为三部分

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  2. Mac安装和卸载HomeBrew

    安装方法: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/ ...

  3. 从bios启动说起

    如果从bios启动说起的话,BIOS去加载bootloader,bootloader去加载操作系统,那么bootloader是怎么找到操作系统的呢?经过一些流程后,它会去找grub:然后通过grub提 ...

  4. c++类定义代码的分离

    类文件 实际工程中,对一个类的说明.架构.描述方法是:    往往分成头文件和实现的源文件,来实现代码的分离 然后,源文件中包含类的头文件... 头文件的包含问题: 类对应的实现文件cpp.main主 ...

  5. ReentrantReadWriteLock分析

    ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁,一个写锁 线程进入读锁的前提条件: 没有其他线程的写锁, 没有写请求或者有读请求,但调用线程和持有锁的线程是同一个 线程进 ...

  6. Java 类引入 学习记录规整

    之前觉得声明一个类,再把另一个包内的声明数值用第一个类打印出来就可以了(加入引入包类) 结果发现是不对的 看了看demo  得出正确结果    ImportTest 被运行 引入下面的Import类 ...

  7. Linux 普通用户拿到root权限及使用szrz命令上传下载文件

    1.如何拿到root权限 在shell里如果看到你的命令输入行最前面显示的是 $符号,说明目前账号只有系统的普通权限. 输入:sudo su 这时能看到shell的输入行最前面已经显示的是#号,说明已 ...

  8. hdu 1573 X问题 两两可能不互质的中国剩余定理

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Desc ...

  9. webstorm注册码 永久有效!!! 前端工程师福利

    2RRJMBXW33-eyJsaWNlbnNlSWQiOiIyUlJKTUJYVzMzIiwibGljZW5zZWVOYW1lIjoi5b285bK4IHNvZnR3YXJlMiIsImFzc2lnb ...

  10. C# 二进制字符串互转

    1.字符转二进制 public static string ChineseToBinary(string s) { byte[] data = Encoding.Unicode.GetBytes(s) ...