Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用
Entity Framework使用Code First方式时,实体之间已经配置好关系,根据实际情况某些情况下需要同时获取导航属性,比如获取商品的同时需要获取分类属性(导航属性),或者基于优化方面考虑等,下面来看一个例子
例子中有会员实体类(Member)与角色实体类(Role),Role与Member的关系是1:n,控制台应用程序代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
EFContext<Member> efMemberContext = new EFContext<Member>();
var members = efMemberContext.Set<Member>().ToList();
foreach (Member item in members)
{
Console.WriteLine(item.Role.Name);
}
Console.ReadKey();
}
}
}
EFContext类、Member类、Role类以及Mapping类如下:
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions; namespace ConsoleApplication2
{
public partial class EFContext<T> : DbContext where T : class
{
public EFContext(): base("name=MyConnectionString")
{
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<EFContext<T>> (null);
modelBuilder.Configurations.Add(new MemberMap());
modelBuilder.Configurations.Add(new RoleMap());
base.OnModelCreating(modelBuilder);
} public DbSet<T> Table { get; set; } public IQueryable<T> GetList(Expression<Func<T,bool>> where)
{
return this.Table.Where(where);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApplication2
{
public partial class Member
{
public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } public bool Delete{ get; set; } public int RoleId { get; set; } public virtual Role Role { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApplication2
{
public class MemberMap : EntityTypeConfiguration<Member>
{
public MemberMap()
{
this.ToTable("Member");
this.HasKey(m => m.Id);
this.HasRequired(m => m.Role).WithMany(r => r.Members).HasForeignKey(m => m.RoleId);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApplication2
{
public partial class Role
{
public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Member> Members { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApplication2
{
public class RoleMap: EntityTypeConfiguration<Role>
{
public RoleMap()
{
this.ToTable("Role");
this.HasKey(r => r.Id);
}
}
}
数据库中现有数据如下:


运行程序 ,在SQL Profiler中看到生成了如下的语句:
1. 执行efMemberContext.DbSet<Member>().ToList();生成的SQL:

2. foreach循环了五次,每次生成一条SQL,如下:


这里省略描述了其中三条SQL,SQL语句类似,只是读取Role属性时根据不同的RoleId获取信息,所以只是参数值 不同
从上面的例子可以看出循环几次为了获取导航属性而生成了几条SQL,如果数据库里表有数据量很大,这样的方式对性能的影响可想而知。 根据上面的例子,现在想有没有一种方法在获取Member的同时获取Role信息,也就是生成的SQL是两个表inner join ,于是Include就发挥了作用了。改写Main()方法中的代码如下:
var members = efMemberContext.Set<Member>().Include("Role").ToList();
上面是获取Member时同时获取导航属性Role信息,这样在生成SQL里就是inner join ,再次运行程序,这里可以看到,在SQL Profiler中只执行了一次SQL,而SQL是带inner join的形式

上面两种方式的控制台输出如下:

这里可能有人会有疑问了,如里EF通用类封装了没有公开DbSet<T>类型的属性或者只有IQueryable<T>类型的返回,又或者DbSet<T>().Where(e => true)之后再想Include怎么办?
如果是使用Entity Framework,System.Data.Entity.QueryableExtensions类封装了IIQueryable<T>的扩展方法,其中有Include扩展方法,引用命名空间System.Data.Entity可以使用。
下面是获取RoleId<5的会员信息与对应的角色信息:
EFContext<Member> efMemberContext = new EFContext<Member>();
var members = efMemberContext.Set<Member>().Where(m =>m.RoleId < ).Include("Role").ToList();
foreach (Member item in members)
{
Console.WriteLine("{0}:{1}",item.Name,item.Role.Name);
}
Console.ReadKey();

运行程序,如下:


Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用的更多相关文章
- C#扫盲之:带你掌握C#的扩展方法、以及探讨扩展方法的本质、注意事项
1.为什么需要扩展方法 .NET3.5给我们提供了扩展方法的概念,它的功能是在不修改要添加类型的原有结构时,允许你为类或结构添加新方法. 思考:那么究竟为什么需要扩展方法呢,为什么不直接修改原有类型呢 ...
- 【转载】C#扫盲之:带你掌握C#的扩展方法、以及探讨扩展方法的本质、注意事项
1.为什么需要扩展方法 .NET3.5给我们提供了扩展方法的概念,它的功能是在不修改要添加类型的原有结构时,允许你为类或结构添加新方法. 思考:那么究竟为什么需要扩展方法呢,为什么不直接修改原有类型呢 ...
- Entity Framework Core的坑:Skip/Take放在Select之前造成Include的实体全表查询
今天将一个迁移至 ASP.NET Core 的项目放到一台 Linux 服务器上试运行.站点启动后,浏览器打开一个页面一直处于等待状态.接着奇怪的事情发生了,整个 Linux 服务器响应缓慢,ssh命 ...
- 使用jquery获取url及url参数的方法及定义JQuery扩展方法
1.jquery获取url很简单,代码如下: window.location.href; 其实只是用到了javascript的基础的window对象,并没有用jquery的知识. 2.jquery获取 ...
- System.Web.Mvc.HtmlHelper<dynamic>”没有名为“Partial”的适用方法,但似乎有一个具有该名称的扩展方法。扩展方法不能进行动态调度。请考虑强制转换动态参数,或调用该扩展方法但不使用扩展方法语法。
MVC 调用分布式图,传了没有定义的参数,,参数写得不对
- 浅析Entity Framework Core2.0的日志记录与动态查询条件
前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core2.0的日志记录与动态查询条件 去 ...
- AppBox升级进行时 - Entity Framework的增删改查
AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. Entity Framework新增数据 以新增用户为例,作为对比,先来看下使 ...
- Entity Framework Code First执行SQL语句、视图及存储过程
1.Entity Framework Code First查询视图 Entity Framework Code First目前还没有特别针对View操作的方法,但对于可更新的视图,可以采用与Table ...
- 关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明
一.首先了解下Entity Framework 自动关联查询: Entity Framework 自动关联查询,有三种方法:Lazy Loading(延迟加载),Eager Loading(预先加载) ...
随机推荐
- 从网上找的Android实用代码,记录备用
1.获取应用程序下所有Activity public static ArrayList<String> getActivities(Context ctx) { ArrayList< ...
- 基于Centos搭建 Hadoop 伪分布式环境
软硬件环境: CentOS 7.2 64 位, OpenJDK- 1.8,Hadoop- 2.7 关于本教程的说明 云实验室云主机自动使用 root 账户登录系统,因此本教程中所有的操作都是以 roo ...
- Swift 柯里化
前言 由于柯里化在业务层的应用较少,所以从 Swift 3.0 开始移除了柯里化的用法,但是 Swift 的很多底层特性是使用柯里化来表达的. 1.柯里化 1.1 柯里化简介 柯里化(Currying ...
- 12C -- ORA-65048 ORA-65048
创建common user的时候报错: $ sqlplus '/as sysdba' SQL*Plus: Release 12.2.0.1.0 Production on Tue Apr 18 11: ...
- javascript es6 箭头函数
1.箭头函数示例 let add = (a,b) => a + b //没有语句块时,默认作为返回值 add(1,2); var multi = (a,b) => {ret ...
- ESXi创建磁盘命令
[root@esx421 SAN]# vmkfstools -d thick -a lsilogic -c 10G lun00.vmdk Incorrect disk option "thi ...
- 初试 Kubernetes 集群中使用 Traefik 反向代理
初试 Kubernetes 集群中使用 Traefik 反向代理 2017年11月17日 09:47:20 哎_小羊_168 阅读数:12308 版权声明:本文为博主原创文章,未经博主允许不得转 ...
- Sass的安装(windows 10)
1.下载ruby 下载地址:https://rubyinstaller.org/downloads/ 如果觉得下载速度过慢,可以在我的百度去下载: 链接:https://pan.baidu.com/s ...
- WebRTC 配置环境
复制文件到指定文件路径 cp -rf /home/leehongee/LeeHonGee/jdk1.7.0_45 /usr/lib/jvm 创建文件夹 mkdir jvm 修改环境变量 sudo ...
- AutoIt 软件自动化操作
AutoIt 目前最新是v3版本,这是一个使用类似BASIC脚本语言的免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作. 它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现 ...