MVC3+EF4.1学习系列(九)-----EF4.1其他的一些技巧的使用

上节通过一系列重构 简单的项目就实现了 不过还有些EF的功能没有讲 这节就通过项目 讲讲EF其他的功能与技巧

一.直接执行SQL语句

通常来讲 EF 不用写SQL语句的  但是 在有些场合  比如对生成的SQL语句 觉得不满意 要做优化  或者做报表统计时 要写很变态的SQL语句

再或者 批量操作等   这个时候 使用ORM的弱点就显露了出来 但是 做为优秀的ORM框架  EF 是支持原生态的SQL的   这里面 提供了三种方法

1. DbSet.SqlQuery   有跟踪状态的查询 

2. DbDatabase.SqlQuery   没有跟踪状态的查询  

3. DbDatabase.SqlCommand 直接执行SQL语句 一般用来  批量 增删改

下面 让我们来看下使用方法

再上篇的公共资源库里  添加方法

   public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)        {            return dbSet.SqlQuery(query, parameters);        }

public virtual IEnumerable<TEntity> GetwhithdbSql(string query, params object[] parameters)        {            return context.Database.SqlQuery<TEntity>(query, parameters);        }

通过对比 来介绍下 第一个和第二个的区别~~

在课程控制器下 分别执行这两个方法

  var query = "SELECT * FROM Course WHERE CourseID = @p0";            Course course = unitofwork.CourseRepository.GetWithRawSql(query,id).Single();            EntityState state = unitofwork.GetState(course);            string name=course.Department.Name;

Course coursetwo = unitofwork.CourseRepository.GetwhithdbSql(query, id).Single();            EntityState statetwo = unitofwork.GetState(coursetwo);            string nametwo = coursetwo.Department.Name;

执行后的结果

1.先来看第一个  他的状态是unchanged  也就说 他加入了context上下文中  有跟踪状态

并且下面顺利读取出course.Department.Name   也就是可以读取到导航属性

2.再看来看第二个 他的状态是detached 并没有加入到 context上下文中  没有有跟踪状态

所以 我们下面的读取导航属性的内容时  会报错~~

3.再来说说DbDatabase.SqlCommand  这个比较简单 增删改用这个不错  下面说个批量更新的例子~

假设有需求 更新所有的课程学分为N时   在这种批量操作时 用ORM 框架 就会不太方便了 这时我们可以用这个直接执行SQL语句

这个业务属于课程的  所以继承通用资源库类  代码如下

using System;using ContosoUniversity.Models;

namespace ContosoUniversity.DAL{    public class CourseRepository : GenericRepository<Course>    {        public CourseRepository(SchoolContext context)            : base(context)        {        }

public int UpdateCourseCredits(int multiplier)        {            return context.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);        }

}}

修改上篇的UnitOfWork类 

private CourseRepository courseRepository;

public CourseRepository CourseRepository{    get    {

if (this.courseRepository == null)        {            this.courseRepository = new CourseRepository(context);        }        return courseRepository;    }}

控制器如下

public ActionResult UpdateCourseCredits(int? multiplier){    if (multiplier != null)    {        ViewBag.RowsAffected = unitOfWork.CourseRepository.UpdateCourseCredits(multiplier.Value);    }    return View();}

最后添加视图~~

运行结果图

二.无跟踪查询

EF再默认的时候给我们开启了跟踪查询  这个跟踪的是什么呢? 先来介绍下这个  看下面的代码

 Department  duplicateDepartment = db.Departments                    .Where(d => d.InstructorID == department.InstructorID)                    .FirstOrDefault();

duplicateDepartment.Name = "wuhawuha";

bool IsUpdate=db.Entry<Department>(duplicateDepartment).Property(p => p.Name).IsModified; //是否修改         string now= db.Entry<Department>(duplicateDepartment).Property(p => p.Name).CurrentValue; //现在的值         string before = db.Entry<Department>(duplicateDepartment).Property(p => p.Name).OriginalValue; //以前的值

我们先随便查出一个院系信息 修改他的名字 这是我们会通过上面的信息 得到现在的值  以前的值  这就是跟踪帮我们做的事  下面看下无跟踪的

实现无跟踪很简单  在查询时 加上asNoTracking() 即可. 加上后我们发现 明明发生变化了 但是IsUpdate依然为false。而且在 获取以前的值时 抛出了异常。

通常情况 我们并不需要跟踪这些状态 可以在查询时去掉跟踪查询,可以使得性能 得到提升~ 以前一直觉得去掉这个会影响导航属性的使用 但是测试后  并没有影响~

这个跟踪查询 还会带来另一个问题    看下面的图

这是在修改前  加了句  先查询这个修改的 再修改 这是就会报错  ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

遇到这个错误  在查询时 加上asNoTracking() 即可.  目前在用EF时 个人并不喜欢有跟踪状态~~ 喜欢加上asNoTracking()

三.使用代理

了解过ORM框架的  我们知道 导航属性 使用了代理模式 ,这个代理 也是跟导航属性有关的 。 禁用代理 可以提高序列化的速度 .

关闭代理的代码为在继承 dbcontext 的类里  加上如下代码

   public SchoolContext()        {             this.Configuration.ProxyCreationEnabled = false;        }

下面展示下有代理和没有代理的区别  先看有代理时

我们的Administrator 是导航属性  我们看到 得到的是一串很长的数字和字母的组合  在下面 访问这个Administrator属性时 会通过延迟加载 才得到Administrator属性

再来看代理关闭时的图

看我们的导航属性 都为null 不能正确获得导航属性

四.自动检测功能

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

在上面的方法中 会调用自动检测功能。  这个功能默认是开启的  当我们在做批量操作时 可以关闭这个来提高性能 .例如

using (var context = new UnicornsContext()){    try    {        context.Configuration.AutoDetectChangesEnabled = false;

// Make many calls in a loop        foreach (var unicorn in myUnicorns)        {            context.Unicorns.Add(unicorn);        }    }    finally    {        context.Configuration.AutoDetectChangesEnabled = true;    }}

这个自动检测 在检测什么 我还没自己研究 希望知道的朋友告知下~~

请大家参考这个MSDN自动检测的介绍

五.非常好的进一步学习EF的资料

1.Fluent API 的方式定义与数据库映射

2.利用特性实现与数据库的映射

3.EF的一些公约的介绍

4.EF团队博客

5.Julie Lerman‘s blog

6.EF性能优化的一些建议

7.分析EF的数据库活动

六.总结

原文的内容总算带上自己的理解 给全写完了

以后就是写写自己的东西了    下一个写EF处理树形结构~~

哦~ 对了   再次贴下 原文的 下载地址

时间: 2024-08-07 20:07:32

MVC3+EF4.1学习系列(九)-----EF4.1其他的一些技巧的使用的相关文章

MVC3+EF4.1学习系列(十一)----EF4.1常见的问题解决

博客写了10篇了~有很多朋友私信问了一些问题,而且很多问题 大家问的都一样 这里说说这些常见问题的解决办法.如果大家有更好的解决办法~也希望分享出来 问题大概为这几个 一.ef4.1 codeFirst 修改表结构 增加字段等 EF code first需要重新生成库导致数据丢失的问题. 二.ef4.1 没有了edmx等复杂的东西 变得简单 干净  但如何使用存储过程,存储过程可以返回表 可以返回数值 也有可能是执行修改 删除 增加等  该怎么做? 三.ef4.1 如何使用数据库视图?每个视图都

MVC3+EF4.1学习系列(二)-------基础的增删改查和持久对象的生命周期变化

上篇文章中 我们已经创建了EF4.1基于code first的例子  有了数据库 并初始化了一些数据  今天这里写基础的增删改查和持久对象的生命周期变化 学习下原文先把运行好的原图贴来上~~ 一.创建详细页 首先 我们先在控制器下 添加详细页的方法 因为这篇文章后面要介绍持久对象声明周期的变化 所以在这里先看下有哪些状态 EF里一共有这五中生命状态类型 其实 看名字我们可以大概猜测出个一二三来~~  游离的 未改变的  新添加的  已删除的 修改的  但是是怎么变化的能 我们在后面的代码中实践与

MVC3+EF4.1学习系列(一)-------创建EF4.1 code first的第一个实例

基于EF4.1 code first 简单的CRUD  园子中已经有很多了 ~~ 真不想再写这个了 可是为了做一个完整的小demo 从开始 到后面的一些简单重构 还是决定认真把这个写出来 争取写些别人没写到的东西~~ 好了 开始~~ 这次要做的是个学校管理的demo(通俗些) 先建一个MVC3的应用程序  因为我们是code first 所以 开始创建实体类 一.创建Model 学生和学生成绩登记表是一对多的关系  一个学生可以有多次登记 (因为有多个课程)  一个课程也可以有多个登记   可以

MVC3+EF4.1学习系列(七)-----EF并发的处理

看这篇文章之前 推荐园子里的 这个文章已经有介绍了 而且写的很好~~ 可以先看下他的 再看我的 并发 1.悲观并发 简单的说 就是一个用户访问一条数据时 则把这个数据变为只读属性  把该数据变为独占 只有该用户释放了这条数据 其他用户才能修改 这期间如果该用户上个厕所 出去玩一圈 没有退出 则其他人都要等很久 很显然 这不是我们期望的效果  也不是这篇文章讨论的重点 2.乐观并发 乐观并发相对悲观并发,用户读取数据时不锁定数据.当一个用户更新数据时,系统将进行检查,查看该用户读取数据后其他用户是

MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式

通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种方式 已经跟踪生成的SQL来检测是否满意 通过这节学习 来明白什么时候用哪个~~ 一.三种加载 1.延迟加载 这是原文中的图 大家可以去看下  我模仿上面的做了个测试  出现了  已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭. 我的解决办法是    var departments

MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目

项目最基础的东西已经结束了,但是现在我们的项目还不健全  不利于测试 重复性代码多   层与层之间耦合性高  不利于扩展等问题.今天的这章 主要就是解决这些问题的.再解决这些问题时,自己也产生了很多疑问,理解的也并不是很透彻 ,希望我的疑问能在这里得到解答~~ 一.模式介绍 1.Repository 在<企业架构模式>中,通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调.还有请大家参考这个  P OF EAA详细介绍 然后说下我对这个的感觉和疑问   怎么都觉得这个Re

MVC3+EF4.1学习系列(十)----MVC+EF处理树形结构

通过前几篇文章 我们处理了 一对一, 一对多,多对多关系 很好的发挥了ORM框架的做用 但是 少说了一种 树形结构的处理, 而这种树形关系 我们也经常遇到,常见的N级类别的处理, 以及经常有数据与类别挂钩.今天主要写下EF处理树形结构以及 MVC如何展示树形结构. 前面几篇的例子 一直用的是一个例子,内容是连贯的.这篇是完全单独的~ 先来说下工作中会遇到的常见场景 针对这几个场景来处理~ 1.类别 a.类别可以有无限级别 b.类别的最末端 不确定是第几级 某个节点 可以到二级 其他的节点 有可能

Quartz.NET学习系列(九)--- XML任务配置

Quartz.NET除了可以代码定义触发器.任务之外,还可以由XML定义这两个对象.其实Quartz.NET的理想架构是:计划管理容器作为服务器运行在服务机上,而触发器.任务的添加可通过自定义任务管理软件向服务器上添加特定的任务计划. 这时就要求数据的持久化以及服务器的容错性了,后面几篇文章将会介绍持久化以及集群相关内容. VS的XML只能提示 第一篇已经将Quartz.NET下载过来了,在路径doc/xml/文件加下可以找到job_scheduling_data_2_0.xsd vs的智能提示

目标跟踪学习系列九:Struck:Structured Output Tracking with Kernels头文件代码框架

我们先来看一下整个的头文件的构成: 其中: config.h :   配置头文件,里面定义了一个类:class Config.主要定义的是特征的类型,核函数的类型等等. Features.h:定义了一个Class Features .里面定义了int 型的m_featureCount//特征计数Eigen::VectorXd m_featVec 存储特征的向量.其中使用了inline内联函数(inline 说明这个函数是内联的,在编译过程中内联函数会直接被源代码替换,提高执行效率 如果类中的某个