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 篇。

  1. Entity Framework 4.1 之一 : 基础
  2. Entity Framework 4.1 之二 : 覆盖默认的约定
  3. Entity Framework 4.1 之三 : 贪婪加载和延迟加载
  4. Entity Framework 4.1 之四:复杂类型
  5. Entity Framework 4.1 之五:多对多的关系
  6. Entity Framework 4.1 之六:乐观并发
  7. Entity Framework 4.1 之七:继承
  8. Entity Framework 4.1 之八:绕过 EF 查询映射

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

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

有三个 API 支持:

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

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

public int ExecuteSqlCommand( string sql, params object [] parameters);

第二个有点意思。

public IEnumerable < TElement > SqlQuery < TElement > ( string sql, params object [] 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 类的定义。

public
class
SprocReport
{

public
int
LegalEntityBaseID {
get
;
set
; }

public
string
EntityName {
get
;
set
; }
}

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

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

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

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

protected
override
void
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 。这可以用,但这是一种特殊的技巧。

参考页面:

http://www.yuanjiaocheng.net/ASPNET-CORE/core-view-start.html

http://www.yuanjiaocheng.net/webapi/webapi-filters.html

http://www.yuanjiaocheng.net/CSharp/csharp-dynamic-type.html

http://www.yuanjiaocheng.net/CSharp/Csharp-Exception.html

http://www.yuanjiaocheng.net/CSharp/csharp-generic-dictionary.html

http://www.yuanjiaocheng.net/Linq/linq-query-syntax.html

http://www.yuanjiaocheng.net/ASPNET-CORE/first.html

http://www.yuanjiaocheng.net/mvc/mvc-helper-textbox.html

http://www.yuanjiaocheng.net/ASPNET-CORE/core-authorize-attribute.html

http://www.yuanjiaocheng.net/CSharp/csharp-array.html

http://www.yuanjiaocheng.net/CSharp/Csharp-sortedlist.html

时间: 2024-10-23 13:50:38

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

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 第一个没有什么

Entity Framework多表多条件动态查询

方式一  Linq To Entity形式: /// <summary> /// 查询的数据 /// </summary> /// <param name="order">升序asc(默认)还是降序desc</param> /// <param name="sort">排序字段</param> /// <param name="search">查询条件</p

Entity Framework技巧系列之八 - Tip 29 – 34

提示29. 怎样避免延迟加载或Load()阅读器问题 如果你有如下这样的代码: 1 var results = from c in ctx.Customers 2 where c.SalesPerson.EmailAddress == "-" 3 select c; 4 foreach(var customer in results) 5 { 6 Console.WriteLine(customer.Name); 7 if (IsInteresting(customer)) 8 { 9

Entity Framework 5.0系列之EF概览

概述 在开发面向数据的软件时我们常常为了解决业务问题实体.关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案.ADO.NET Entity Framework是.NET开发中一种由ADO.NET驱动的ORM框架,使用Entity Framework开发人员可以不必考虑数据的基础数据表和列,在处理数据时能够以更高的抽象级别进行工作,并能够以相对传统开发编写更少的代码来创建和维护应用程序. 我们知道面向对象的编程与数据存储系统的交换提出了一个难题:类结构通常同关系数据表组织结构

Entity Framework 4.1 Change Tracker EF状态跟踪函数解析

Skip to main content Data Developer Center Sign in United States (English) HomeLibraryLearnDownloadsSupportCommunityForums Change Tracker API Entity Framework 4.1 Change Tracker Julie Lerman http://thedatafarm.com Published: June 2011 Download the co

Entity Framework with MySQL 学习笔记一(查询)

参考 : http://msdn.microsoft.com/en-us/data/jj574232.aspx EF 查询基本上有3中 默认是 Lazy Loading 特色是只有在需要数据的时候EF才会像数据库请求,它不会使用任何inner join 比如我们有一个产品,有很多颜色,(1对多) 那么我们想把每个产品和颜色统统选出来 using (EFDB db = new EFDB()) { var prods = db.prods.ToList(); //像数据库请求prods, 但是不会包

Entity Framework Code First主外键关系映射约定

本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个不同表之间可以存在外键依赖关系,一个表自身也可以有自反关系(表中的一个字段引用主键,从而也是外键字段). Entity Framework Code First默认多重关系的一些约定规则: 一对多关系:两个类中分别包含一个引用和一个集合属性,也可以是一个类包含另一个类的引用属性,或一个类包含另一个类

Entity Framework学习六:一些常用查询技术

var people = context.People .Where(p => p.PersonState == PersonState.Active) .OrderBy(p => p.LastName) .ThenBy(p => p.FirstName) .Select(p => new { p.LastName, p.FirstName, p.PersonType.TypeName }); foreach (var person in people) { Console.Wri

Entity Framework 第四篇 优化SQL查询

Expression<Func<TEntity, bool>>与Func<TEntity, bool>的异同 public IList<TEntity> Search<TEntity>(Expression<Func<TEntity, bool>> predicate = null) where TEntity : class { if (predicate == null) { return dbContext.Set&