IEnumerable的一些基本方法 补充
接上一篇,我们发现两表连接方式默认为内连接,而我们在SQL中常用到的左连接没有封装方法。换句话说,微软放弃两表左连或右连的这种做法(只有在2个表都存在值时,这样的连接才有意义)。
如果要实现表的左连接,就不能调用他现有的封装方法了,可以用LINQ来实现。
var joinTable = (from left in table1.AsEnumerable() join right in table2.AsEnumerable() on left["ID"].ToString() equals right["ID"].ToString() into newTable from right in newTable.DefaultIfEmpty() select new { LeftID = left["ID"].ToString(), RightID = right != null ? right["ID"].ToString() : default(string), LeftName = left["Name"].ToString(), RightName = right != null ? right["Name"].ToString() : default(string) }).ToList(); joinTable.ForEach(t => Console.WriteLine("{0}\t{1}\t{2}\t{3}", t.LeftID, t.RightID, t.LeftName, t.RightName));
功能是实现了,但是这样又要憋死一群强迫症患者,非要用Join封装方法来实现这个功能。
那我们就来手动封装一个左连接方法吧。
public static IEnumerable<Result> LeftJoin<TOuter, TInner, TKey, Result>( this IEnumerable<TOuter> outer , IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector , Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector , IEqualityComparer<TKey> comparer) { if (outer == null) throw new ArgumentException("outer"); if (inner == null) throw new ArgumentException("inner"); if (outerKeySelector == null) throw new ArgumentException("outerKeySelector"); if (innerKeySelector == null) throw new ArgumentException("innerKeySelector"); if (resultSelector == null) throw new ArgumentException("resultSelector"); return LeftJoinImpl(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer ?? EqualityComparer<TKey>.Default); } static IEnumerable<Result> LeftJoinImpl<TOuter, TInner, TKey, Result>( IEnumerable<TOuter> outer, IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector , Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector , IEqualityComparer<TKey> comparer) { var innerLookup = inner.ToLookup(innerKeySelector, comparer); foreach (var outerElment in outer) { var outerKey = outerKeySelector(outerElment); var innerElements = innerLookup[outerKey]; if (innerElements.Any()) foreach (var innerElement in innerElements) yield return resultSelector(outerElment, innerElement); else yield return resultSelector(outerElment, default(TInner)); } }
PS:以上这段代码转载自stackoverflow.com
var joinTable = table1.AsEnumerable().LeftJoin(table2.AsEnumerable(), left => left["ID"].ToString(), right => right["ID"].ToString(), (left, right) => new { LeftID = left["ID"].ToString(), RightID = right != null ? right["ID"].ToString() : default(string), LeftName = left["Name"].ToString(), RightName = right != null ? right["Name"].ToString() : default(string) }, null).ToList(); joinTable.ForEach(t => Console.WriteLine("{0}\t{1}\t{2}\t{3}", t.LeftID, t.RightID, t.LeftName, t.RightName));
是不是和之前的Join方法一样,这样用起来很方便了吧。