时间:2021-07-01 10:21:17 帮助过:16人阅读
- 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 < 5).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的使用
标签:exp toolbar man foreach ping any frame ram span