using EntityFrameworkCore.Data; using EntityFrameworkCore.Domain; using Microsoft.EntityFrameworkCore; using var context = new DeadBallZoneLeagueDbContext(); // context.Database.Migrate(); // Can be used to automatically migrate on run. context.Database.EnsureCreated(); // var teamOne = await context.Teams.FirstAsync(t => t.Id == 1); // var teamTwo = await context.Teams.FirstAsync(t => t.Id == 2); // var teamThree = await context.Teams.SingleAsync(t => t.Id == 3); // var teamFour = await context.Teams.SingleOrDefaultAsync(t => t.Id == 3); // There is no entry for coaches yet, this function will provide a null to coach. // Rather than raise: "System.InvalidOperationException: Sequence contains no elements." // var firstCoach = await context.Coaches.FirstOrDefaultAsync(); var details = await context.TeamsAndLeaguesView.ToListAsync(); async Task ProjectionAndAnonymousDataTypes() { var teams = await context.Teams .Select(t => new TeamDetailsDTO { TeamId = t.Id, TeamName = t.Name, CoachName = t.Coach.Name, TotalHomeGoals = t.HomeMatches.Sum(m => m.HomeTeamScore), TotalAwayGoals = t.AwayMatches.Sum(m => m.AwayTeamScore) }) .ToListAsync(); foreach (var team in teams) { Console.WriteLine($"{team.TeamName} - {team.CoachName} | H: {team.TotalHomeGoals} | A: {team.TotalAwayGoals}"); } } async Task FilterScoredHomeMatches() { // Get teams where they scored on home matches. var teams = await context.Teams .Include(t => t.Coach) .Include(t => t.HomeMatches.Where(m => m.HomeTeamScore > 0)) .ToListAsync(); foreach (var team in teams) { Console.WriteLine($"{team.Name} - {team.Coach.Name}"); foreach (var match in team.HomeMatches) { Console.WriteLine($"Score: {match.HomeTeamScore}"); } } } async Task InsertMatches() { var match1 = new Match { AwayTeamId = 10, HomeTeamId = 12, HomeTeamScore = 1, AwayTeamScore = 0, Date = new DateTime(2025, 6, 10), TicketPrice = 20 }; var match2 = new Match { AwayTeamId = 6, HomeTeamId = 9, HomeTeamScore = 1, AwayTeamScore = 0, Date = new DateTime(2025, 6, 11), TicketPrice = 20 }; var match3 = new Match { AwayTeamId = 13, HomeTeamId = 15, HomeTeamScore = 1, AwayTeamScore = 0, Date = new DateTime(2025, 6, 12), TicketPrice = 20 }; var match4 = new Match { AwayTeamId = 4, HomeTeamId = 11, HomeTeamScore = 0, AwayTeamScore = 1, Date = new DateTime(2025, 6, 12), TicketPrice = 20 }; await context.AddRangeAsync(match1, match2, match3, match4); await context.SaveChangesAsync(); } async Task ExplicitLoadingExample() { var league = await context.FindAsync(1); if (!league.Teams.Any()) { Console.WriteLine("Teams have not been loaded."); } await context.Entry(league) .Collection(l => l.Teams) .LoadAsync(); if (league.Teams.Any()) { foreach (var team in league.Teams) { Console.WriteLine($"{team.Name}"); } } } async Task EagerLoadingExample() { var leagues = await context.Leagues .Include(l => l.Teams) .ThenInclude(t => t.Coach) .ToListAsync(); foreach (var league in leagues) { Console.WriteLine($"League - {league.Name}"); foreach (var team in league.Teams) { Console.WriteLine($"* {team.Name} - {team.Coach.Name}"); } } } async Task InsertRelatedData() { // Insert record with a Foreign Key. var match = new Match { AwayTeamId = 1, HomeTeamId = 2, AwayTeamScore = 0, HomeTeamScore = 0, Date = new DateTime(2025, 6, 1), TicketPrice = 20 }; await context.AddAsync(match); await context.SaveChangesAsync(); // Insert Parent/Child var team = new Team { Name = "Neo Istanbul", Coach = new Coach { Name = "Gimbal Wizbouski" } }; await context.AddAsync(team); await context.SaveChangesAsync(); // Insert Parent with Children. var league = new League { Name = "Star League", Teams = new List { new Team { Name = "Neo Cairo", Coach = new Coach { Name = "Damon Pulsar" } }, new Team { Name = "Cyborgs", Coach = new Coach { Name = "C-1" } } } }; await context.AddAsync(league); await context.SaveChangesAsync(); } async Task ExecuteDelete(string name) { // var coaches = await context.Coaches.Where(c => c.Name == name).ToListAsync(); // context.RemoveRange(coaches); // await context.SaveChangesAsync(); // Simplified: await context.Coaches.Where(c => c.Name == name).ExecuteDeleteAsync(); } async Task ExecuteUpdate(int id) { await context.Coaches .Where(c => c.Id == id) .ExecuteUpdateAsync(set => set.SetProperty(c => c.CreatedDate, DateTime.UtcNow)); } async Task DeleteCoach(int id) { var coach = await context.Coaches.FindAsync(id); if (coach != null) { context.Remove(coach); // context.Entry(coach).State = EntityState.Deleted; await context.SaveChangesAsync(); } } async Task UpdateCoach() { var coach = await context.Coaches.FindAsync(1); coach.CreatedDate = DateTime.UtcNow; await context.SaveChangesAsync(); } async Task UpdateCoachNoTracking() { var coach = await context.Coaches .AsNoTracking() .FirstOrDefaultAsync(c => c.Id == 1); // .FindAsync(1); // cannot be used when using no-tracking. coach.CreatedDate = DateTime.UtcNow; Console.WriteLine(context.ChangeTracker.DebugView.LongView); context.Update(coach); // Set Entity state to be updated. // Note that also other fields are considered "updated/modified", such as the CreatedDate. // You can also use: // context.Entry(coach).State = EntityState.Modified; Console.WriteLine(context.ChangeTracker.DebugView.LongView); await context.SaveChangesAsync(); } async Task InsertCoach(string name) { var coach = new Coach { Name = name, CreatedDate = DateTime.UtcNow }; await context.Coaches.AddAsync(coach); Console.WriteLine(context.ChangeTracker.DebugView.LongView); await context.SaveChangesAsync(); // If you have a list, you can use a batch insert, instead of a loop: // await context.Coaches.AddRangeAsync(coaches); } async Task ListVSIQueryableCall() { Console.WriteLine("Enter '1' for team with Id 1 or enter '2' for teams that contain 'Neo'"); var option = Convert.ToInt32(Console.ReadLine()); List teamsAsList = new List(); // After executing ToList, the records are stored in memory. // Operations after that, are also done in memory. teamsAsList = await context.Teams.ToListAsync(); if (option == 1) { teamsAsList = teamsAsList.Where(t => t.Id == 1).ToList(); } else if (option == 2) { teamsAsList = teamsAsList.Where(t => t.Name.Contains("Neo")).ToList(); } foreach (var team in teamsAsList) { Console.WriteLine(team.Name); } // Records stay as IQueryable until the ToList function is called, then the final query is performed. var teamsAsQueryable = context.Teams.AsQueryable(); if (option == 1) { teamsAsQueryable = teamsAsQueryable.Where(t => t.Id == 1); } else if (option == 2) { teamsAsQueryable = teamsAsQueryable.Where(t => t.Name.Contains("Neo")); } // the actual query: teamsAsList = await teamsAsQueryable.ToListAsync(); foreach (var team in teamsAsList) { Console.WriteLine(team.Name); } } async Task TrackedQuery() { // EF Core tracks objects that are returned by queries. // This is less useful in disconnected applictations like APIs and Web applications. var teams = await context.Teams .AsNoTracking() .ToListAsync(); foreach (var team in teams) { Console.WriteLine(team.Name); } } async Task SkipAndTakeTeams() { var recordCount = 3; var page = 0; var next = true; while (next) { var teams = await context.Teams.Skip(page * recordCount).Take(recordCount).ToListAsync(); foreach (var team in teams) { Console.WriteLine(team.Name); } Console.WriteLine("Enter 'true' for next set of records, or 'false to quit.'"); next = Convert.ToBoolean(Console.ReadLine()); if (!next) break; page += 1; } } async Task OrderedTeams() { var orderedTeam = await context.Teams .OrderByDescending(t => t.Name) .ToListAsync(); foreach (var team in orderedTeam) { Console.WriteLine(team.Name); } } async Task GroupedTeams() { var groupedTeams = context.Teams .GroupBy(t => t.CreatedDate.Date); foreach (var groupedTeam in groupedTeams) { Console.WriteLine(groupedTeam.Key); Console.WriteLine(groupedTeam.Sum(t => t.Id)); foreach (var team in groupedTeam) { Console.WriteLine(team.Name); } } } async Task CountFunctionsTeams(int id) { var numberOfTeams = await context.Teams.CountAsync(t => t.Id > id); Console.WriteLine($"Number of teams with ID > {id}: {numberOfTeams}"); var maxTeams = await context.Teams.MaxAsync(t => t.Id); Console.WriteLine($"Max teams: {maxTeams}"); var minTeams = await context.Teams.MinAsync(t => t.Id); Console.WriteLine($"Min teams: {minTeams}"); var averageTeams = await context.Teams.AverageAsync(t => t.Id); Console.WriteLine($"Average teams: {averageTeams}"); var sumTeams = await context.Teams.SumAsync(t => t.Id); Console.WriteLine($"Sum team IDs: {sumTeams}"); } async Task GetAllTeamsQuerySyntax(string searchTerm) { var teams = await ( from team in context.Teams where EF.Functions.Like(team.Name, $"%{searchTerm}%") select team) .ToListAsync(); foreach (var team in teams) { Console.WriteLine(team.Name); } } async Task PrintTeams() { var teams = await context.Teams.ToListAsync(); foreach (var team in teams) { Console.WriteLine(team.Name); } } async Task PrintFilteredTeams() { Console.WriteLine("Enter search term: "); var searchTerm = Console.ReadLine(); // var filteredTeams = await context.Teams.Where(t => t.Name.Contains(searchTerm)).ToListAsync(); var filteredTeams = await context.Teams.Where(t => EF.Functions.Like(t.Name, $"%{searchTerm}%")).ToListAsync(); foreach (var team in filteredTeams) { Console.WriteLine(team.Name); } } async Task PrintTeamById(int id) { // Selection based on finding the Primary Key. var teamBasedOnId = await context.Teams.FindAsync(id); if (teamBasedOnId != null) { Console.WriteLine(teamBasedOnId.Name); } } async Task SelectQuery() { var items = await context.Teams .Select(t => new { t.Name, t.CreatedDate }) .ToListAsync(); foreach (var item in items) { Console.WriteLine($"{item.Name} - {item.CreatedDate}"); } } async Task SelectQueryDTO() { var items = await context.Teams .Select(t => new TeamInfoDTO { Name = t.Name, Created = t.CreatedDate }) .ToListAsync(); foreach (var item in items) { Console.WriteLine($"{item.Name} - {item.Created}"); } } class TeamInfoDTO { public DateTime Created { get; set; } public string Name { get; set; } } class TeamDetailsDTO { public int TeamId { get; set; } public string TeamName { get; set; } public string CoachName { get; set; } public int TotalHomeGoals { get; set; } public int TotalAwayGoals { get; set; } }