当前位置:Gxlcms > 数据库问题 > Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用

Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用

时间:2021-07-01 10:21:17 帮助过:16人阅读

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Data.Entity;
  7. namespace ConsoleApplication2
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. EFContext<Member> efMemberContext = new EFContext<Member>();
  14. var members = efMemberContext.Set<Member>().ToList();
  15. foreach (Member item in members)
  16. {
  17. Console.WriteLine(item.Role.Name);
  18. }
  19. Console.ReadKey();
  20. }
  21. }
  22. }
技术分享
  1. EFContext类、Member类、Role类以及Mapping类如下:
技术分享 技术分享
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Linq.Expressions;
  8. namespace ConsoleApplication2
  9. {
  10. public partial class EFContext<T> : DbContext where T : class
  11. {
  12. public EFContext(): base("name=MyConnectionString")
  13. {
  14. }
  15. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  16. {
  17. Database.SetInitializer<EFContext<T>> (null);
  18. modelBuilder.Configurations.Add(new MemberMap());
  19. modelBuilder.Configurations.Add(new RoleMap());
  20. base.OnModelCreating(modelBuilder);
  21. }
  22. public DbSet<T> Table { get; set; }
  23. public IQueryable<T> GetList(Expression<Func<T,bool>> where)
  24. {
  25. return this.Table.Where(where);
  26. }
  27. }
  28. }
技术分享 技术分享 技术分享
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace ConsoleApplication2
  7. {
  8. public partial class Member
  9. {
  10. public int Id { get; set; }
  11. public string Name { get; set; }
  12. public string Password { get; set; }
  13. public bool Delete{ get; set; }
  14. public int RoleId { get; set; }
  15. public virtual Role Role { get; set; }
  16. }
  17. }
技术分享 技术分享 技术分享
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity.ModelConfiguration;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace ConsoleApplication2
  8. {
  9. public class MemberMap : EntityTypeConfiguration<Member>
  10. {
  11. public MemberMap()
  12. {
  13. this.ToTable("Member");
  14. this.HasKey(m => m.Id);
  15. this.HasRequired(m => m.Role).WithMany(r => r.Members).HasForeignKey(m => m.RoleId);
  16. }
  17. }
  18. }
技术分享 技术分享 技术分享
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace ConsoleApplication2
  7. {
  8. public partial class Role
  9. {
  10. public int Id { get; set; }
  11. public string Name { get; set; }
  12. public virtual ICollection<Member> Members { get; set; }
  13. }
  14. }
技术分享 技术分享 技术分享
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity.ModelConfiguration;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace ConsoleApplication2
  8. {
  9. public class RoleMap: EntityTypeConfiguration<Role>
  10. {
  11. public RoleMap()
  12. {
  13. this.ToTable("Role");
  14. this.HasKey(r => r.Id);
  15. }
  16. }
  17. }
技术分享

数据库中现有数据如下:

技术分享

 

技术分享

 

运行程序 ,在SQL Profiler中看到生成了如下的语句:

1. 执行efMemberContext.DbSet<Member>().ToList();生成的SQL:

技术分享

 

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

技术分享

技术分享

这里省略描述了其中三条SQL,SQL语句类似,只是读取Role属性时根据不同的RoleId获取信息,所以只是参数值 不同

从上面的例子可以看出循环几次为了获取导航属性而生成了几条SQL,如果数据库里表有数据量很大,这样的方式对性能的影响可想而知。 根据上面的例子,现在想有没有一种方法在获取Member的同时获取Role信息,也就是生成的SQL是两个表inner join ,于是Include就发挥了作用了。改写Main()方法中的代码如下:

  1. 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的会员信息与对应的角色信息:

技术分享
  1. EFContext<Member> efMemberContext = new EFContext<Member>();
  2. var members = efMemberContext.Set<Member>().Where(m =>m.RoleId < 5).Include("Role").ToList();
  3. foreach (Member item in members)
  4. {
  5. Console.WriteLine("{0}:{1}",item.Name,item.Role.Name);
  6. }
  7. Console.ReadKey();
技术分享

技术分享

 

 运行程序,如下:

技术分享

 

 技术分享

Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用

标签:exp   toolbar   man   foreach   ping   any   frame   ram   span   

人气教程排行