zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }
    View Code
    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; }
        }
    }
    View Code
    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);
            }
        }
    }
    View Code
    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; }
        }
    }
    View Code
    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);
            }
        }
    }
    View Code

    数据库中现有数据如下:

     

     

    运行程序 ,在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 < 5).Include("Role").ToList();
    foreach (Member item in members)
    {
        Console.WriteLine("{0}:{1}",item.Name,item.Role.Name);
    }
    Console.ReadKey();

     

     运行程序,如下:

     

     

     

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/godbell/p/7348411.html
Copyright © 2011-2022 走看看