class DefectsOpenedByDate { static void Main() //使用join...into子句进行分组连接 累计计算五月份每一天缺陷的数目 { var dates = new DateTimeRange(SampleData.Start, SampleData.End); //{Chapter11.Queries.DateTimeRange} //这句调用了SampleData的构造函数 var query = from date in dates join defect in SampleData.AllDefects on date equals defect.Created.Date //defect 这句没有跳转到其他语句,这是个匿名方法 //{ 1: MP3 files crash system (2013/5/1-2013/5/23, Showstopper/Accepted, Tim Trotter -> Darren Dahlia)} //{ 2: Text is too big(2013/5/3-2013/5/9, Trivial/Closed, Deborah Denton -> n/a)} //{ 3: Sky is wrong shade of blue (2013/5/3-2013/5/19, Minor/Fixed, Colin Carton -> Tara Tutu)} //{ 4: Can't play files more than 200 bytes long (2013/5/4-2013/5/23, Major/Reopened, Darren Dahlia -> Darren Dahlia)} //{ 5: Installation is slow (2013/5/6-2013/5/15, Trivial/Fixed, Tim Trotter -> Tim Trotter)} //{ 6: DivX is choppy on Pentium 100 (2013/5/7-2013/5/29, Major/Accepted, Mary Malcop -> Darren Dahlia)} //{ 7: Client acts as virus (2013/5/8-2013/5/10, Showstopper/Closed, Deborah Denton -> n/a)} //{ 8: Subtitles only work in Welsh(2013/5/8-2013/5/23, Major/Fixed, Darren Dahlia -> Tim Trotter)} //{ 9: Voice recognition is confused by background noise (2013/5/9-2013/5/15, Minor/Closed, Colin Carton -> n/a)} //{10: User interface should be more caramelly (2013/5/9-2013/5/9, Trivial/Created, Tim Trotter -> Darren Dahlia)} //{11: Burning a CD makes the printer catch fire (2013/5/10-2013/5/29, Showstopper/Closed, Mary Malcop -> n/a)} //{12: Peer to peer pairing passes parameters poorly (2013/5/10-2013/5/12, Minor/Accepted, Tara Tutu -> Darren Dahlia)} //{13: Delay when sending message (2013/5/11-2013/5/20, Minor/Fixed, Darren Dahlia -> Tara Tutu)} //{14: Volume control needs to go to 11 (2013/5/11-2013/5/11, Minor/Created, Mary Malcop -> Darren Dahlia)} //{15: Splash screen fades too quickly (2013/5/11-2013/5/15, Minor/Fixed, Colin Carton -> Tara Tutu)} //{16: Text box doesn't keep up with fast typing (2013/5/12-2013/5/12, Major/Accepted, Deborah Denton -> Deborah Denton)} //{17: Password displayed in plain text (2013/5/12-2013/5/13, Showstopper/Closed, Darren Dahlia -> n/a)} //{18: Play button points the wrong way (2013/5/12-2013/5/17, Major/Fixed, Tim Trotter -> Tim Trotter)} //{19: Wizard needed for CD burning (2013/5/13-2013/5/20, Minor/Fixed, Colin Carton -> Colin Carton)} //{20: Subtitles don't display during fast forward (2013/5/13-2013/5/14, Trivial/Accepted, Mary Malcop -> Darren Dahlia)} //{21: Memory leak when watching Memento (2013/5/13-2013/5/13, Trivial/Created, Darren Dahlia -> Deborah Denton)} //{22: Profile screen shows login count of -1 (2013/5/13-2013/5/20, Major/Accepted, Deborah Denton -> Deborah Denton)} //{23: Server crashes under heavy load (3 users) (2013/5/13-2013/5/17, Major/Accepted, Tim Trotter -> Deborah Denton)} //{24: Unable to connect to any media server (2013/5/15-2013/5/18, Showstopper/Reopened, Tara Tutu -> Darren Dahlia)} //{25: UI turns black and white when playing old films (2013/5/15-2013/5/25, Minor/Fixed, Deborah Denton -> Tara Tutu)} //{26: Password reset changes passwords for all users (2013/5/16-2013/5/18, Showstopper/Closed, Mary Malcop -> n/a)} //{27: Modern music sounds rubbish (2013/5/17-2013/5/17, Trivial/Created, Tim Trotter -> Darren Dahlia)} //{28: Webcam makes me look bald (2013/5/18-2013/5/27, Showstopper/Fixed, Tim Trotter -> Tim Trotter)} //{29: Sound is distorted when speakers are underwater (2013/5/18-2013/5/18, Major/Created, Colin Carton -> Darren Dahlia)} //{30: Japanese characters don't display properly (2013/5/19-2013/5/23, Major/Accepted, Darren Dahlia -> Deborah Denton)} //{31: Video takes 100% of CPU (2013/5/20-2013/5/22, Major/Accepted, Tara Tutu -> Deborah Denton)} //{32: DVD Easter eggs unavailable (2013/5/22-2013/5/22, Trivial/Created, Tim Trotter -> Darren Dahlia)} //{33: Transparency is high for menus to be readable (2013/5/23-2013/5/25, Minor/Accepted, Mary Malcop -> Deborah Denton)} //{34: About box is missing version number (2013/5/24-2013/5/29, Minor/Fixed, Colin Carton -> Colin Carton)} //{35: Logs record confidential conversations (2013/5/25-2013/5/30, Major/Reopened, Tim Trotter -> Darren Dahlia)} //{36: Profanity filter is too aggressive (2013/5/27-2013/5/29, Minor/Fixed, Deborah Denton -> Tara Tutu)} //{37: Full screen mode fails on dual monitors (2013/5/27-2013/5/27, Minor/Created, Tara Tutu -> Deborah Denton)} //{38: Visualization hypnotises pets (2013/5/28-2013/5/29, Minor/Accepted, Colin Carton -> Deborah Denton)} //{39: Resizing while typing loses input (2013/5/29-2013/5/29, Trivial/Created, Mary Malcop -> Darren Dahlia)} //{40: Network is saturated when playing WAV file (2013/5/30-2013/5/31, Minor/Fixed, Tim Trotter -> Tim Trotter)} //{41: Media library tells user to keep the noise down (2013/5/31-2013/5/31, Major/Created, Tara Tutu -> Darren Dahlia)} //跳转到public IEnumerator<DateTime> GetEnumerator() 方法 into joined select new { Date=date, Count=joined.Count() }; //query //{System.Linq.Enumerable.GroupJoinIterator<System.DateTime,Chapter11.Model.Defect,System.DateTime,<>f__AnonymousType9<System.DateTime,int>>} foreach (var grouped in query)//in 会执行public IEnumerator<DateTime> GetEnumerator() //grouped { Date = {2013/5/1 0:00:00}, Count = 1 } //{ Date = {2013/5/2 0:00:00}, Count = 0 } //{ Date = {2013/5/3 0:00:00}, Count = 2 } //{ Date = {2013/5/4 0:00:00}, Count = 1 } //{ Date = {2013/5/5 0:00:00}, Count = 0 } //{ Date = {2013/5/6 0:00:00}, Count = 1 } //{ Date = {2013/5/7 0:00:00}, Count = 1 } //{ Date = {2013/5/8 0:00:00}, Count = 2 } //{ Date = {2013/5/9 0:00:00}, Count = 2 } //{ Date = {2013/5/10 0:00:00}, Count = 2 } //{ Date = {2013/5/11 0:00:00}, Count = 3 } //{ Date = {2013/5/12 0:00:00}, Count = 3 } //{ Date = {2013/5/13 0:00:00}, Count = 5 } //{ Date = {2013/5/14 0:00:00}, Count = 0 } //{ Date = {2013/5/15 0:00:00}, Count = 2 } //{ Date = {2013/5/16 0:00:00}, Count = 1 } //{ Date = {2013/5/17 0:00:00}, Count = 1 } //{ Date = {2013/5/18 0:00:00}, Count = 2 } //{ Date = {2013/5/19 0:00:00}, Count = 1 } //{ Date = {2013/5/20 0:00:00}, Count = 1 } //{ Date = {2013/5/21 0:00:00}, Count = 0 } //{ Date = {2013/5/22 0:00:00}, Count = 1 } //{ Date = {2013/5/23 0:00:00}, Count = 1 } //{ Date = {2013/5/24 0:00:00}, Count = 1 } //{ Date = {2013/5/25 0:00:00}, Count = 1 } //{ Date = {2013/5/26 0:00:00}, Count = 0 } //{ Date = {2013/5/27 0:00:00}, Count = 2 } //{ Date = {2013/5/28 0:00:00}, Count = 1 } //{ Date = {2013/5/29 0:00:00}, Count = 1 } //{ Date = {2013/5/30 0:00:00}, Count = 1 } //{ Date = {2013/5/31 0:00:00}, Count = 1 } { Console.WriteLine("{0:d}: {1}", grouped.Date, grouped.Count); } } } public class SampleData { public static readonly DateTime Start = May(1); public static readonly DateTime End = May(31); public static DateTime May(int day) { return new DateTime(2013, 5, day); } static SampleData() { projects = new List<Project> { Projects.SkeetyMediaPlayer, Projects.SkeetyTalk, Projects.SkeetyOffice }; users = new List<User> { Users.TesterTim, Users.TesterTara, Users.DeveloperDeborah, Users.DeveloperDarren, Users.ManagerMary, Users.CustomerColin }; subscriptions = new List<NotificationSubscription> { new NotificationSubscription { Project=Projects.SkeetyMediaPlayer, EmailAddress="[email protected]" }, new NotificationSubscription { Project=Projects.SkeetyTalk, EmailAddress="[email protected]" }, new NotificationSubscription { Project=Projects.SkeetyOffice, EmailAddress="[email protected]" }, new NotificationSubscription { Project=Projects.SkeetyMediaPlayer, EmailAddress="[email protected]"} }; //41个缺陷不贴代码 defects = new List<Defect> { new Defect { Project = Projects.SkeetyMediaPlayer, Created = May(1), CreatedBy = Users.TesterTim, Summary = "MP3 files crash system", Severity = Severity.Showstopper, AssignedTo = Users.DeveloperDarren, Status = Status.Accepted, LastModified = May(23) }, }; } public static DateTime May(int day)//把day带进去 看缺陷的May的参数 { return new DateTime(2013, 5, day); } } public class Defect { public Defect() { ID = StaticCounter.Next(); } } public static class StaticCounter { static int next = 1; public static int Next() { return next++; } } public class DateTimeRange : IEnumerable<DateTime> { private readonly DateTime start; private readonly DateTime end; public DateTimeRange(DateTime start, DateTime end) //start{2013/5/1 0:00:00} end{2013/5/31 0:00:00} { this.start = start; this.end = end; } public IEnumerator<DateTime> GetEnumerator() { for (DateTime current = start; current <= end; current = current.AddDays(1)) //current {2013/5/1 0:00:00} { yield return current;//返回到 on date equals defect.Created.Date } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
没有贴出所有代码,原有的代码太长了。还隐藏了一些细节,缺陷就有41条
Count()本身使用立即执行的模式,就是遍历它被调用的序列中的所有元素,不过我们只能在
表达式的投影部分调用它,所以它就成为Lambda表达式的一部分。这意味着,依然可以实现
延迟执行:直到开始执行foreach循环才会进行求值。
编译器将分组连接转译为简单地调用GroupJoin方法,就像Join一样。
同内连接一致,如果分组连接后面紧跟着select子句,那么投影就用作GroupJoin调用的结果
选择器,否则,就引入一个透明标识符。
输出
2013/5/1: 1
2013/5/2: 0
2013/5/3: 2
2013/5/4: 1
2013/5/5: 0
2013/5/6: 1
2013/5/7: 1
2013/5/8: 2
2013/5/9: 2
2013/5/10: 2
2013/5/11: 3
2013/5/12: 3
2013/5/13: 5
2013/5/14: 0
2013/5/15: 2
2013/5/16: 1
2013/5/17: 1
2013/5/18: 2
2013/5/19: 1
2013/5/20: 1
2013/5/21: 0
2013/5/22: 1
2013/5/23: 1
2013/5/24: 1
2013/5/25: 1
2013/5/26: 0
2013/5/27: 2
2013/5/28: 1
2013/5/29: 1
2013/5/30: 1
2013/5/31: 1