EF的表左连接方法Include和Join

在EF中表连接常用的有Join()和Include(),两者都可以实现两张表的连接,但又有所不同。

例如有个唱片表Album(AlbumId,Name,CreateDate,GenreId),表中含外键GenreId连接流派表Genre(GenreId,Name)。每个唱片归属唯一一个流派,一个流派可以对应多个唱片。

1.Join(),两表不必含有外键关系,需要代码手动指定连接外键相等(具有可拓展性,除了值相等,还能指定是>,<以及其他对两表的相应键的关系),以及结果字段。

重载方式(是扩展方法,第一个参数带this,代表自身):

复制代码
复制代码
1.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector);

2.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector, IEqualityComparer<TKey> comparer);
复制代码
复制代码

那么可以这么写两个表的连接:

var wholeRecord = dc.Album.Join(dc.Genre, a => a.GenreId, g => g.GenreId, (a, g) => new { a.AlbumId,a.Name,g.GenreId,g.Name;

这样就选取除了两表的AlbumId,Name,GenreId,Name。

  1. public object GetListAdmin()  
  2.         {  
  3.             //return db_C56.Admins  
  4.             //   .Where(a => a.Status != "D").ToList();  
  5.   
  6.             var query1 = db_C56.Admins.Join(db_C56.Area, a => a.AreaID, ar => ar.ID, (a, ar) => new  
  7.             {  
  8.                 userName = a.UserName,  
  9.                 pwd = a.Password,  
  10.                 dName = a.DisplayName,  
  11.                 areaId = a.AreaID,  
  12.                 hasNode = a.HasNode,  
  13.                 roleName = a.RoleName,  
  14.                 status = a.Status,  
  15.                 areaName = ar.Name  
  16.             });  
  17.   
  18.             var query = from a in db_C56.Admins  
  19.                         join ar in db_C56.Area  
  20.                         on a.AreaID equals ar.ID  
  21.                         where a.Status != "D"  
  22.                         select new  
  23.                         {  
  24.                             userName = a.UserName,  
  25.                             pwd = a.Password,  
  26.                             dName = a.DisplayName,  
  27.                             areaId = a.AreaID,  
  28.                             hasNode = a.HasNode,  
  29.                             roleName = a.RoleName,  
  30.                             status = a.Status,  
  31.                             areaName = ar.Name  
  32.                         };  
  33.             return query.ToList().Select(C => new Admin  
  34.             {  
  35.                 UserName = C.userName,  
  36.                 Password = C.pwd,  
  37.                 DisplayName = C.dName,  
  38.                 AreaID = C.areaId,  
  39.                 AreaPath = C.areaName,  
  40.                 HasNode = C.hasNode,  
  41.                 RoleName = C.roleName,  
  42.                 Status = C.status,  
  43.             });  
  44.         }  

2.Include(),两表必须含有外键关系,只需要指定键名对应的类属性名即可,不需指定结果字段(即全部映射)。默认搜索某表时,不会顺带查询外键表,直到真正使用时才会再读取数据库查询;若是使用 Include(),则会在读取本表时把指定的外键表信息也读出来。

重载方式:

//位于namespace System.Data.Entity.Infrastructure
public DbQuery<TResult> Include(string path);
//位于namespace System.Data.Entity,务必引入才能找到该方法。否则只看到上个方法
public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> source, Expression<Func<T, TProperty>> path) where T : class;
        public static IQueryable<T> Include<T>(this IQueryable<T> source, string path) where T : class;

可以这么写:

//EF已经生成了Album和Genre的数据库映射模型类以及导航属性
var wholeRecord=dc.Album.Include("Genre");
//或者
//var wholeRecord=dc.Album.Include(a=>Genre);

这样数据库就执行了一个左连接,把Album和Genre的所有字段全部连起来了,并且Include()是立即查询的,像ToList()一样,不会稍后延迟优化后再加载。

这样其实效率很低,因为如果两张表记录很大,那么连接是个费时费资源的事情,建议少用,或者先筛选出需要的结果集再连接。

因为向往 所以选择了远方 因为无可依靠 所以必须坚强
原文地址:https://www.cnblogs.com/Alex80/p/8343568.html