在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。
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()一樣,不會稍后延遲優化后再加載。
這樣其實效率很低,因為如果兩張表記錄很大,那么連接是個費時費資源的事情,建議少用,或者先篩選出需要的結果集再連接。