public class DictionaryResult<TKey, TValue> { public TKey Key { get; set; } public IEnumerable<TValue> Values { get; set; } } public class JoinResult<TLeft, TRight> { public TLeft Left { get; set; } public TRight Right { get; set; } } public static class JoinExtension { /// <summary> /// 兩表JOIN,以Key匹配,僅返回交集 /// </summary> /// <typeparam name="T1"></typeparam> /// <typeparam name="T2"></typeparam> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="query"></param> /// <param name="another"></param> /// <param name="keySelector"></param> /// <param name="keySelector2"></param> /// <param name="resultSelector"></param> /// <returns></returns> public static IQueryable<TResult> InnerJoin<T1, T2, TKey, TResult>(this IQueryable<T1> query, IQueryable<T2> another, Expression<Func<T1, TKey>> keySelector, Expression<Func<T2, TKey>> keySelector2, Expression<Func<T1, T2, TResult>> resultSelector ) { return query.Join(another, keySelector, keySelector2, resultSelector); } /// <summary> /// 兩表JOIN,左表爲主,以Key匹配右表數據。結果表示方式以左錶行爲Key,右錶行爲Values /// </summary> /// <typeparam name="T1"></typeparam> /// <typeparam name="T2"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="query"></param> /// <param name="another"></param> /// <param name="keySelector"></param> /// <param name="keySelector2"></param> /// <returns></returns> public static IQueryable<DictionaryResult<T1, T2>> LeftJoinToDictionary<T1, T2, TKey>(this IQueryable<T1> query, IQueryable<T2> another, Expression<Func<T1, TKey>> keySelector, Expression<Func<T2, TKey>> keySelector2 ) { return query.GroupJoin(another, keySelector, keySelector2, (x, y) => new DictionaryResult<T1, T2> { Key = x, Values = y }); } /// <summary> /// 兩表JOIN,左表爲主,以Key匹配右表數據。結果必有左表全部行,右表未有匹配行時其對應屬性爲NULL /// </summary> /// <typeparam name="T1"></typeparam> /// <typeparam name="T2"></typeparam> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="query"></param> /// <param name="another"></param> /// <param name="keySelector"></param> /// <param name="keySelector2"></param> /// <param name="resultSelector"></param> /// <returns></returns> public static IQueryable<TResult> LeftJoin<T1, T2, TKey, TResult>(this IQueryable<T1> query, IQueryable<T2> another, Expression<Func<T1, TKey>> keySelector, Expression<Func<T2, TKey>> keySelector2, Expression<Func<JoinResult<T1, T2>, TResult>> resultSelector ) { return query.LeftJoinToDictionary(another, keySelector, keySelector2) .SelectMany(x => x.Values.DefaultIfEmpty(), (x, y) => new JoinResult<T1, T2> { Left = x.Key, Right = y }) .Select(resultSelector); } /// <summary> /// 兩表JOIN,右表爲主,以Key匹配左表數據。結果表示方式以右錶行爲Key,左錶行爲Values /// </summary> /// <typeparam name="T1"></typeparam> /// <typeparam name="T2"></typeparam> /// <typeparam name="TKey"></typeparam> /// <param name="query"></param> /// <param name="another"></param> /// <param name="keySelector"></param> /// <param name="keySelector2"></param> /// <returns></returns> public static IQueryable<DictionaryResult<T2, T1>> RightJoinToDictionary<T1, T2, TKey>(this IQueryable<T1> query, IQueryable<T2> another, Expression<Func<T1, TKey>> keySelector, Expression<Func<T2, TKey>> keySelector2 ) { return another.GroupJoin(query, keySelector2, keySelector, (x, y) => new DictionaryResult<T2, T1> { Key = x, Values = y }); } /// <summary> /// 兩表JOIN,右表爲主,以Key匹配左表數據。結果必有右表全部行,左表未有匹配行時其對應屬性爲NULL /// </summary> /// <typeparam name="T1"></typeparam> /// <typeparam name="T2"></typeparam> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="query"></param> /// <param name="another"></param> /// <param name="keySelector"></param> /// <param name="keySelector2"></param> /// <param name="resultSelector"></param> /// <returns></returns> public static IQueryable<TResult> RightJoin<T1, T2, TKey, TResult>(this IQueryable<T1> query, IQueryable<T2> another, Expression<Func<T1, TKey>> keySelector, Expression<Func<T2, TKey>> keySelector2, Expression<Func<JoinResult<T1, T2>, TResult>> resultSelector ) { return another.RightJoinToDictionary(query, keySelector2, keySelector) .SelectMany(x => x.Values.DefaultIfEmpty(), (x, y) => new JoinResult<T1, T2> { Left = x.Key, Right = y }) .Select(resultSelector); } }