zoukankan      html  css  js  c++  java
  • 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 。这可以用,但这是一种特殊的技巧。

  • 相关阅读:
    Echart 动态生成series数据
    转换Excel格式
    .NET接收邮件下载邮件附件——openpop.net
    百度Echart 地图
    mobiscroll 日期问题
    jQuery自动完成插件flexselect
    HTML5 video 连续播放视频
    team foundation server 工具的使用
    实现主成分分析与白化
    白化(预处理步骤)【转】
  • 原文地址:https://www.cnblogs.com/ghw0501/p/4927638.html
Copyright © 2011-2022 走看看