public ReviewModel Build(long revision) { var sourceCode = _sourceControl.GetRevision(revision); var commit = _database.Commits.FirstOrDefault(c => c.Revision == revision); var comments = _database.Comments.Where(comment => comment.Revision == revision).ToList(); var model = new ReviewModel { Author = commit.Author, Message = commit.Message, Revision = commit.Revision, Timestamp = commit.Timestamp, ApprovedBy = commit.ApprovedBy, Files = new List <FileModel>(), }; var commitComments = comments .Where(c => c.ReplyTo == null && string.IsNullOrEmpty(c.File) && !c.IsLike) .OrderBy(c => c.Id); Func <Comment, CommentModel> recursiveConvert = default(Func <Comment, CommentModel>); recursiveConvert = (comment) => { var converted = new CommentModel { Id = comment.Id, Author = comment.User, Text = comment.Text, FileId = comment.File, LineId = comment.LineId, Timestamp = comment.Timestamp, Replies = new List <CommentModel>() }; foreach (var reply in comment.Replies) { converted.Replies.Add(recursiveConvert(reply)); } return(converted); }; model.CommitComments = commitComments.Select(c => recursiveConvert(c)).ToList(); foreach (var fileDiff in sourceCode.FileDiffs.OrderBy(f => f.Name)) { var fileModel = new FileModel { Name = fileDiff.Name, ModText = fileDiff.FileState.ToString(), Lines = new List <LineModel>(), Revision = revision }; model.Files.Add(fileModel); foreach (var lineDiff in fileDiff.Lines) { var lineModel = new LineModel { Id = lineDiff.Id, Revision = revision, File = fileModel.Name, Text = lineDiff.Text, AddedLineNumber = lineDiff.AddedLineNumber, RemovedLineNumber = lineDiff.RemovedLineNumber, ChangeState = lineDiff.Changed, Comments = new List <CommentModel>(), Likes = new List <string>(), Author = model.Author, }; fileModel.Lines.Add(lineModel); var lineComments = comments .Where(c => c.ReplyTo == null && c.LineId == lineModel.Id && c.File == lineModel.File) .OrderBy(c => c.Id); lineModel.Comments = lineComments.Where(c => !c.IsLike).Select(c => recursiveConvert(c)).ToList(); lineModel.Likes = lineComments.Where(c => c.IsLike).Select(c => c.User).ToList(); } } return(model); }