Entity Framework 4.1 绕过 EF 查询映射

原文:http://blog.csdn.net/eqera/article/details/8411437

这是这了系列的最后一篇,我将讨论如何绕过 EF 的查询映射。

像所有优秀的框架一样,EF 知道它并不能优秀到覆盖所有的角落,通过允许直接访问数据库,EF 支持开放底层的 ADO.NET 框架。

有三个 API 支持:

  • DbContext.Database.ExecuteSqlCommand
  • DbContext.Database.SqlQuery
  • DbSet.SqlQuery

第一个没有什么特别,就像典型的 ADO.NET 中的 SqlCommand。

publicint ExecuteSqlCommand(string sql, paramsobject[] parameters);

第二个有点意思。

public IEnumerable<TElement> SqlQuery<TElement>(string sql, paramsobject[] parameters);

我们可以使用这个方法直接将 SQL 命令发送到数据库,不管是存储过程,还是临时的 SQL。与 ADO.NET 的区别在于它能够将查询结果的 DataReader 中的数据直接转换为实体对象。

TElement 可以是任何类。重要的是 EF 不会跟踪返回的对象,即使他们真的是实体类型的对象。这与第三个 DbSet 不同,第三种方式会跟踪返回的对象。

让我们试一下 DbContext.Database.SqlQuery:

public IEnumerable<SprocReport> GetEntityList() 

return Database.SqlQuery<SprocReport>("SELECT LegalEntityBaseID, EntityName FROM dbo.LegalEntity"); 
}

一个最佳实践就是在 DbContext 的派生类中封装这些调用。下面是我们使用的 SprocReport 类的定义。

publicclass SprocReport 

publicint LegalEntityBaseID { get; set; } 
publicstring EntityName { get; set; } 
}

这个类不是实体,而且属性被直接映射:不能控制映射。即使你使用复杂类型,并且覆盖了映射,这些覆盖也不会起作用。

现在看 DbSet.SqlQuery,这个方法返回的实体将会被 EF 跟踪修改,所以,如果你在这些返回的实体上做了修改,当 DbContext.SaveChanges 被调用的时候,将会被处理。从另一个方面来说,也不能覆盖列的映射。

另外一个旁路 EF 映射管理的方法是使用 Entity SQL,记住 EF 将实体模型映射到物理的模型,在转换到本地底层的数据存储(例如 TSQL) 查询之前,先将 LINQ 查询被转化到实体模型上(通过 eSQL 语法)。

举例来说,我们可以创建实体集而不需要在 DbContex 中定义:

protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder) 

base.OnModelCreating(modelBuilder);

modelBuilder.Entity<SimpleEntry>().HasEntitySetName("MyEntry"); 
modelBuilder.Entity<SimpleEntry>().ToTable("MyEntry", "man"); 
modelBuilder.Entity<SimpleEntry>() 
.Property(s => s.ID) 
.HasColumnName("SimpleEntryID"); 
modelBuilder.Entity<SimpleEntry>() 
.Property(s => s.Name) 
.HasColumnName("SimpleEntryName");

}

然后,我们可以暴露出查询:

public IEnumerable<SimpleEntry> GetSimpleEntries() 

IObjectContextAdapter adapter =this; 
var entries = adapter.ObjectContext.CreateQuery<SimpleEntry>("SELECT VALUE MyEntry FROM MyEntry");

return entries; 
}

这里我们使用底层的 ObjectContext 以便查询。这种方式比直接将 SQL 发送到数据库的优势在于,我们可以使用 LINQ 在其上进行查询,最终发送到数据库的 SQL 是合并得到的。因此,我们可以通过从一个返回任何结果的简单查询开始,然后在其上应用 LINQ来得到有效的查询,而不需要在使用方查询整个表。

为了说服我们自己,我刚刚说的是真的,让我们试一下。

public IEnumerable<SimpleEntry> GetSimpleEntries() 

IObjectContextAdapter adapter =this; 
var entries = adapter.ObjectContext.CreateQuery<SimpleEntry>("SELECT VALUE MyEntry FROM MyEntry"); 
var final = from e in entries 
where e.Name == "Mark" 
select e; 
var f = (System.Data.Objects.ObjectQuery<SimpleEntry>)final; 
var s = f.ToTraceString();

return entries; 
}

如果输出 s 的值,可以看到:

SELECT 
[Extent1].[SimpleEntryID]AS[SimpleEntryID], 
[Extent1].[SimpleEntryName]AS[SimpleEntryName] 
FROM[man].[MyEntry]AS[Extent1] 
WHERE N’Mark’ = [Extent1].[SimpleEntryName]

这是 EF 生成的典型的 TSQL, 你会注意到 LINQ 过滤条件被应用到了 SQL 语句中。

现在,如果你希望能够截获实体的 Insert, Update, 和 Delete 操作,就要靠你自己了。你需要重写 DbContext.SaveChanges ,获取特定状态的实体,实现自己的数据操作逻辑来保存修改,然后在调用 base.SaveChanges 之前将这些实体的状态切换到 Unmodified 。这可以用,但这是一种特殊的技巧。

时间: 2024-10-12 19:59:53

Entity Framework 4.1 绕过 EF 查询映射的相关文章

Entity Framework 4.1 之八:绕过 EF 查询映射

原文名称:Entity Framework 4.1: Bypassing EF query mapping (8) 原文地址:http://vincentlauzon.wordpress.com/2011/04/21/entity-framework-4-1-bypassing-ef-query-mapping-8/ 看到 Entity Framework 4.1 推荐英文教程,为了帮大家看起来方便一些,简单翻译一下.这是一个系列,共有 8 篇,这是第 8 篇. Entity Framework

爆料:为什么Entity Framework不能进行跨数据库查询

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在上篇随笔中提到"对于跨数据库查询,我们没有找到通过LINQ to Entities实现的方法".后来仔细想想,从理论来讲,实现跨数据库查询应该不难啊,与非跨数据库查询相比,只是多了个数据库名,比如下面的非跨数据库查询语句: SELE

Entity Framework(实体框架 EF)

什么是Entity Framework呢(下面简称EF)? EF(实体框架)是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架.ORM(对象关系映射框架):指的是面向对象的对象模型和关系型数据库的数据结构之间的相互转换. 如此官方的解释,你懂吗? 我理解的是,业务实体在内存中表现为对象,在数据库中表现为数据,内存中的对象之间,存在关联和继承关系,而在数据库中,关系数据无法直接表达这些关系.而对象-关系映射(ORM)就是解决这一问题的.ORM作为一个中间件,实现程

Entity Framework 使用注意:Where查询条件中用到的关联实体不需要Include

来自博客园开发团队开发前线最新消息: 在Entity Framework中,如果实体A关联了实体B,你想在加载实体A的同时加载实体B.通常做法是在LINQ查询中使用Include().但是,如果你在查询条件中用到了实体B,EF会自动加载实体B,这时Include不仅是多余的,而且还会增加额外的LEFT OUTER JOIN查询,影响性能. 请看我们在博问开发中遭遇这个问题时的一段代码: //For q.cnblogs.com public class QuestionService { priv

Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)

今天乍一看,园子里居然没有关于这个类库的文章,实在是意外毕竟已经有很多介绍EF使用的文章了. E文好的可以直接看https://github.com/loresoft/EntityFramework.Extended 也可以在nuget上直接安装这个包,它的说明有点过时了,最新版本已经改用对IQueryable<T>的扩展,而不是DbSet<T>(已经标记为弃用),所以跟我一样有隔离癖好的就可以大胆使用了.下面介绍如何批量删除.更新.查询. 批量删除 本来我们需要这样删除 ? //

Entity Framework 学习系列(4) - EF 增删改

目录 写在前面 一.开发环境 二.创建项目 三.新增 1.单表新增 2.批量新增 3.多表新增 四.编辑 1.先查询,后编辑 2.创建实体,后编辑 五.删除 写在前面 在上一小节中,学习了如何 通过Code First + MySql 的方式实现数据的迁移. 这一下节中,总结 EF的增删改. 一.开发环境 开发工具:Visual Studio 2019 开发环境:Win 10 家庭版 数据库:MySQL 8.0.17 二.创建项目 1.打开Visual Studio 2019 新建->创建程序台

Entity Framework 第十篇 条件查询

业务类中 我们根据条件来动态的查询 创建IQueryable接口 public IQueryable<TEntity> GetQueryable() { IQueryable<TEntity> query = dbContext.Set<TEntity>(); return query; } 为什么创建IQueryable接口?IQueryable会在调用ToList()或者Count()等方法的时候,才回向数据库查询,所以只会向数据库提交一次带条件的查询语句,从而提升

[Entity Framework]获取部分字段的查询

using (var ObjectContext = new AgentSystemEntities()) { DateTime dt = new DateTime(1997, 1, 1); string entitySQL = "SELECT VALUE Users FROM Users WHERE Users.AddDateTime > @dt;"; ObjectParameter[] ps = { new ObjectParameter("dt", dt

Entity Framework 第六篇 分页查询

目前分页支持单表 public IList<TEntity> GetPaged<TEntity>(out int total, Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, int index = 1, int size = 20) wh