<file_sep>﻿using IdentityModel;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Models
{
	public class Programmer : IdentityUser<Guid>
	{
		[Key]
		public override Guid Id { get; set; }
		public override string PasswordHash { get; set; }
		public State State { get; set; }
		public Country Country { get; set; }
		public Profile Profile { get; set; }
		//public virtual ICollection<Project> Projects { get; set; }
		//public virtual ICollection<WorkExperience> WorkExperiences { get; set; }
		//public virtual ICollection<Qualification> Qualifications { get; set; }
		//public virtual ICollection<Skill> Skills { get; set; }
		//public virtual ICollection<ProgrammerCategory> ProgrammerCategories { get; set; }
		//Add
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface IProfileRepository
	{
		Task<Profile> GetProgrammerProfileAsync(Guid programmerId);
		Task<IEnumerable<Profile>> GetAllProfilesAsync();
		Task<bool> ProgrammerProfileExistsAsync(Guid profileId);
		Task<IEnumerable<Skill>> GetAllSkillsByProgrammerAsync(Guid profileId);
		Task<IEnumerable<Project>> GetAllProjectsByProgrammerAsync(Guid profileId);
		Task<IEnumerable<WorkExperience>> GetAllWorkExperiencesByProgrammerAsync(Guid profileId);
		Task<IEnumerable<Qualification>> GetAllQualificationsByProgrammerAsync(Guid profileId);
		Task<ILookup<Guid, Project>> GetAllProjectsAsync(IEnumerable<Guid> profileIds);
		Task<IDictionary<Guid, Project>> GetProjectsAsync(IEnumerable<Guid> profileIds, CancellationToken token);
	}
}<file_sep>﻿using GraphQL;
using GraphQL.Http;
using GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Api.Middlewares
{
	public class GraphQLRequest
	{
		private JObject _variables;
		public string OperationName { get; set; }
		public string Query { get; set; }
		public JObject Variables
		{
			get => _variables ?? new JObject(new { });
			set => _variables = value;
		}

	}
	public static class GraphQLMiddlewareExtension
	{
		public static void GraphQLMiddleware<TSchema>(this IApplicationBuilder appBuilder) where TSchema: ISchema
		{
			appBuilder.UseMiddleware<GraphQLMiddlware<TSchema>>();
		}
	}

	public class GraphQLMiddlware<TSchema> where TSchema : ISchema
	{
		private readonly RequestDelegate _next;
		private readonly IDocumentExecuter _executor;
		private readonly IDocumentWriter _writer;
		private TSchema Schema { get; }

		public GraphQLMiddlware(RequestDelegate next, TSchema schema,IDocumentExecuter executer,IDocumentWriter writer)
		{
			_next = next;
			Schema = schema;
			_executor = executer;
			_writer = writer;
		}
		public async Task InvokeAsync(HttpContext context)
		{
			// Method is not "POST" & path is not "/graphql"
			if(!context.Request.Method.Equals("post", StringComparison.OrdinalIgnoreCase) && !context.Request.Path.Equals("/graphql"))
			{
				await _next(context);
				return;
			}
			var request = Deserialize<GraphQLRequest>(context.Request.Body);
			var result = await _executor.ExecuteAsync(new ExecutionOptions
			{
				Schema = Schema,
				Query = request.Query,
				OperationName = request.OperationName,
				Inputs=request.Variables.ToInputs()
			});
			context.Response.ContentType = "application/json";
			context.Response.StatusCode = (int)(result.Errors?.Any() == true ? HttpStatusCode.BadRequest : HttpStatusCode.OK);
			//await context.Response.WriteAsync(_writer.Write(result));
			//await context.Response.WriteAsync(_writer.Write(result));
		}

		private static T Deserialize<T>(Stream stream)
		{
			using(var reader = new StreamReader(stream))
			{
				using (var JsonReader = new JsonTextReader(reader))
				{
					return new JsonSerializer().Deserialize<T>(JsonReader);
				}
			}
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Models
{
	public class Qualification
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 5, ErrorMessage = "Skill must be between 5 and 200 characters")]
		public string Title { get; set; }

		[StringLength(2000, MinimumLength = 50, ErrorMessage = "Skill must be between 50 and 2000 characters")]
		public string Description { get; set; }

		[Display(Name = "Started Date")]
		[DataType(DataType.Date)]
		public DateTime StartDate { get; set; }

		[Display(Name = "Finished Date")]
		[DataType(DataType.Date)]
		public DateTime EndDate { get; set; }

		//public Programmer Programmer { get; set; }
		public Profile Profile { get; set; }
	}
}
<file_sep>﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Models
{
	public class GraphQLQueryType
	{
		public string OperationName { get; set; }
		public string Query { get; set; }
		public JObject Variables;
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface IUserRepository
	{
		Task<IEnumerable<Programmer>> GetUsersAsync();
		Task<Programmer> GetUserAsync(Guid userId);
		Task<Profile> GetUserProfileAsync(Guid profileId);
		Task<Country> GetCountryForUserAsync(Guid userId);

		Task<IEnumerable<string>> GetSkillsForUserAsync(Guid userId);
		Task<IEnumerable<string>> GetTechStackForUserAsync(Guid userId);
		Task<bool>UserExistsAsync(Guid userId);
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class QualificationType : ObjectGraphType<Qualification>
	{
		public QualificationType()
		{
			Field(t => t.Id, type: typeof(IdGraphType)).Description("Id of Qualification");
			Field(t => t.Title);
			Field(t => t.Description);
			Field(t => t.StartDate);
			Field(t => t.EndDate);
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.GraphQL.Mutations;
using GraphQL;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL
{
	public class CoderzoneApiSchema : Schema
	{
		public CoderzoneApiSchema(IDependencyResolver resolver) : base(resolver)
		{
			// Query
			Query = resolver.Resolve<CoderzoneApiQuery>();

			// Mutation
			Mutation = resolver.Resolve<CoderzoneApiMutation>();

			// Subscription
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CoderzoneGrapQLAPI.Models;

namespace CoderzoneGrapQLAPI.Services
{
	public class ProgrammerRepository : IProgrammerRepository
	{
		private readonly CoderzoneApiDbContext _programmerContext;

		public ProgrammerRepository(CoderzoneApiDbContext programmerContext)
		{
			_programmerContext = programmerContext;
		}

		public Task<Country> GetCountryForProgrammerAsync(Guid programmerId)
		{
			// Fetch all Qualification from programmer
			return Task.FromResult(_programmerContext.Programmers.Where(p => p.Id==programmerId).Select(c=> c.Country).FirstOrDefault());
		}

		public Task<Programmer> GetProgrammerAsync(Guid programmerId)
		{
			// Empty programmerId field
			if (programmerId == Guid.Empty) throw new ArgumentNullException(nameof(programmerId));

			// Fetch the programmer's profile
			return Task.FromResult(_programmerContext.Programmers.FirstOrDefault(p => p.Id == programmerId));
		}

		public Task<IEnumerable<Programmer>> GetProgrammersAsync()
		{
			return Task.FromResult(_programmerContext.Programmers.AsEnumerable());
		}

		public Task<State> GetStateForProgrammerAsync(Guid programmerId)
		{
			return Task.FromResult(_programmerContext.Programmers.Where(p=> p.Id==programmerId).Select(s=>s.State).FirstOrDefault());
		}

		public Task<bool> ProgrammerExistsAsync(Guid programmerId)
		{
			// bookId is null or empty
			if (programmerId == Guid.Empty) throw new ArgumentNullException(nameof(programmerId));

			// Return true if author with authorId exists
			return Task.FromResult(_programmerContext.Profiles.Any(p => p.Id == programmerId));
		}
	}
}<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface IStateRepository
	{
		Task<ICollection<State>> GetStatesAsync();
		Task<State> GetStateAsync(Guid stateId);
		Task<Country> GetCountryForStateAsync(Guid countryId);
		Task<Programmer> GetUserFromStateAsync(Guid userId);
		Task<Programmer> GetAllUserFromStateAsync(Guid stateId);
		Task<bool> StateExistsAsync(Guid stateId);
		Task<bool> IsDuplicateStateName(Guid stateId, string stateName);
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.controllers;
using CoderzoneGrapQLAPI.GraphQL.Types;
using CoderzoneGrapQLAPI.Services;
using GraphQL;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL
{
	public class CoderzoneApiQuery : ObjectGraphType
	{
		public CoderzoneApiQuery(ICountryRepository country, IProgrammerRepository programmer)
		{
			Field<ListGraphType<CountryType>>(
				name: "countries",
				resolve: context =>
				{
					//var userContext = (CodersGraphQLContext)context.UserContext;
					//userContext.DbContext
					return country.GetCountriesAsync();
				}
				);
			
			Field<ListGraphType<ProgrammerType>>(
				name: "programmers",
				resolve: context => programmer.GetProgrammersAsync()
				);

			Field<ProgrammerType>(
				name: "programmer",
				arguments: new QueryArguments(new QueryArgument<NonNullGraphType<IdGraphType>> { Name = "id" }),
				resolve: context => programmer.GetProgrammerAsync(context.GetArgument<Guid>("id"))
				);
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace CoderzoneGrapQLAPI.Models
{
	public class State
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(100, MinimumLength = 2, ErrorMessage = "State must be between 2 and 100 characters")]
		public string Name { get; set; }

		[Display(Name = "Post Code")]
		[RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Post Code")]
		public string PostCode { get; set; }

		public Country Country { get; set; }
		public virtual ICollection<Programmer> Programmer { get; set; }

	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class CountryType : ObjectGraphType<Country>
	{
		public CountryType(ICountryRepository country)
		{
			Field(c => c.Id, type: typeof(IdGraphType)).Description("Id of the Country");
			Field(c => c.Name);
			Field<ListGraphType<StateType>>(
				"states",
				resolve: context => country.GetStatesForCountryAsync(context.Source.Id)
				); 
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoderzoneGrapQLAPI.Models;
using Microsoft.EntityFrameworkCore;

namespace CoderzoneGrapQLAPI.Services
{
	public class CountryRepository : ICountryRepository
	{
		private readonly CoderzoneApiDbContext _countryContext;

		public CountryRepository(CoderzoneApiDbContext countryContext)
		{
			_countryContext = countryContext;
		}

		// READ OPERATIONS
		public Task<IEnumerable<Country>> GetCountriesAsync()
		{
			return Task.FromResult(_countryContext.Countries.AsEnumerable());
		}

		public Task<Country> GetCountryAsync(Guid countryId)
		{
			if(countryId ==Guid.Empty)
				throw new ArgumentNullException(nameof(countryId));

			return Task.FromResult(_countryContext.Countries.FirstOrDefault(c => c.Id == countryId));
		}

		public Task<Country> GetCountryOfStateAsync(Guid stateId)
		{
			throw new NotImplementedException();
		}

		public Task<Country> GetCountryOfUserAsync(Guid userId)
		{
			throw new NotImplementedException();
		}

		public async Task<IEnumerable<State>> GetStatesForCountryAsync(Guid countryId)
		{
			return await _countryContext.States.Where(s=> s.Country.Id==countryId).ToListAsync();
		}

		public async Task<IEnumerable<Programmer>> GetUsersForCountryAsync(Guid countryId)
		{
			return await _countryContext.Programmers.Where(c => c.Country.Id== countryId).ToListAsync();
		}

		public async Task<bool> CountryExistsAsync(Guid countryId)
		{
			// countryId is null or empty
			if (countryId == Guid.Empty)
				throw new ArgumentNullException(nameof(countryId));

			return await _countryContext.Countries.AnyAsync(c => c.Id == countryId);
		}

		public async Task<bool> IsDuplicateCountryNameAsync(Guid countryId, string countryName)
		{
			// countryId is null or empty
			if (countryId == Guid.Empty)
				throw new ArgumentNullException(nameof(countryId));

			return await _countryContext.Countries.AnyAsync(c => c.Name.Equals(countryName) && c.Id == countryId);
		}


		// CREATE | UPDATE | DELETE OPERATIONS
		public async Task<bool> AddCountryAsync(Country country)
		{
			// Add country Object to country context and save it
			_countryContext.Add(country);
			return await SaveAsync();
		}

		public Task<bool> UpdateCountryAsync(Country country)
		{
			// Update country Object to country context and save it
			_countryContext.Update(country);
			return SaveAsync();
		}

		public async Task<bool> DeleteCountryAsync(Country country)
		{
			// Remove country Object to country context and save it
			_countryContext.Remove(country);
			return await SaveAsync();
		}

		public async Task<bool> SaveAsync() => await _countryContext.SaveChangesAsync() >= 0 ? true : false;
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace CoderzoneGrapQLAPI.Models
{
	public class Country
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(250, MinimumLength = 5, ErrorMessage = "First Name must be between 5 and 250 characters")]
		public string Name { get; set; }

		public virtual ICollection<State> States { get; set; }
		public virtual ICollection<Programmer> Programmers { get; set; }
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using GraphQL.DataLoader;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class ProfileType : ObjectGraphType<Profile>
	{
		public ProfileType(IProfileRepository profile,IProjectRepository project, IProgrammerRepository _programmer,	IDataLoaderContextAccessor dataLoaderAccessor)
		{
			Field(t=> t.Id, type: typeof(IdGraphType)).Description("User Profile Id");
			Field(t => t.FirstName);
			Field(t => t.LastName);
			Field(t => t.Avatar);
			Field(t => t.Bio);
			Field(t => t.City);
			Field(t => t.Street);
			Field(t => t.Number);
			Field(t => t.CreatedAt);
			Field(t => t.UpdatedAt);
			Field(t => t.ProgrammerId, type: typeof(IdGraphType));
			Field(t => t.DatePublished);

			Field<ListGraphType<ProjectType>>(
				name: "projects",
				resolve: context =>
				{
					var loader = dataLoaderAccessor.Context.GetOrAddCollectionBatchLoader<Guid, Project>("GetAllProjectsAsync", profile.GetAllProjectsAsync);
					//var loader = dataLoaderAccessor.Context.GetOrAddBatchLoader<Guid, Project>("GetProjectsAsync", programmer.GetProjectsAsync);
					//return programmer.GetAllProjectsByProgrammerAsync(context.Source.Id);
					//return loader.LoadAsync(context.Source.Id);
					return loader.LoadAsync(context.Source.Id);
				}

			);
			Field<ListGraphType<WorkExperienceType>>(
				name: "works",
				resolve: context => profile.GetAllWorkExperiencesByProgrammerAsync(context.Source.Id)

			);
			Field<ListGraphType<QualificationType>>(
				name: "qualifications",
				resolve: context => profile.GetAllQualificationsByProgrammerAsync(context.Source.Id)

			);
			Field<ListGraphType<SkillType>>(
				name: "skills",
				resolve: context => profile.GetAllSkillsByProgrammerAsync(context.Source.Id)
			);
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Models
{
	public class Skill
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 5, ErrorMessage = "Skill must be between 5 and 200 characters")]
		public string Name { get; set; }

		//public Programmer Programmer { get; set; }
		public Profile Profile { get; set; }
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.GraphQL.Types;
using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using GraphQL;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Mutations
{
	public class CoderzoneApiMutation : ObjectGraphType
	{
		public CoderzoneApiMutation(ICountryRepository countryRepository)
		{
			///TODO:
			FieldAsync<CountryType>(
				Name = "AddCountry",
				arguments: new QueryArguments(new QueryArgument<NonNullGraphType<CountryInputType>> { Name = "country" }),
				resolve: async context=>
				{
					var countryToCreate = context.GetArgument<Country>("country");
					// Make sure country is not already in the database
					var countryInDb = countryRepository.GetCountriesAsync().Result.FirstOrDefault(c=> string.Equals(c.Name, countryToCreate.Name, StringComparison.OrdinalIgnoreCase));
					if(countryInDb !=null)
					{
						context.Errors.Add(new ExecutionError($"The Country '{countryToCreate.Name}' already exists!"));
						return null;
					}
					// Make sure a country was added successfully to database
					if (!await countryRepository.AddCountryAsync(countryToCreate))
					{
						context.Errors.Add(new ExecutionError($"Something went wrong saving {countryToCreate.Name}"));
						return null;
					}
					return countryToCreate;
				}
			);
			FieldAsync<CountryType>(
				Name="UpdateCountry",
				arguments: new QueryArguments(
					new QueryArgument<NonNullGraphType<IdGraphType>> { Name = "countryId" },
					new QueryArgument<NonNullGraphType<CountryInputType>> { Name = "country" }),
				resolve: async context =>
				{
					var countryId = context.GetArgument<Guid>("countryId");
					var countryInfoToUpdate = context.GetArgument<Country>("country");

					// country Ids do not match
					if (countryId != countryInfoToUpdate.Id)
					{
						context.Errors.Add(new ExecutionError($"Bad Request!"));
						return null;
					}
					// Country does not exist in database
					//var ctup = await countryRepository.CountryExistsAsync(countryId);
					var countryInfoToUpdateOld = await countryRepository.GetCountryAsync(countryId);
					if (countryInfoToUpdateOld == null)
					{
						context.Errors.Add(new ExecutionError($"{countryInfoToUpdate.Name} already exists!"));
						return null;
					}
					// Country is a duplicate country
					if (await countryRepository.IsDuplicateCountryNameAsync(countryId, countryInfoToUpdate.Name))
					{
						context.Errors.Add(new ExecutionError($"The Country '{countryInfoToUpdate.Name}' already exists!"));
						return null;
					}

					// Now try to update the country
					//countryInfoToUpdate.Id = countryId;
					countryInfoToUpdateOld.Name = countryInfoToUpdate.Name;
					if (!await countryRepository.UpdateCountryAsync(countryInfoToUpdateOld))
					{
						context.Errors.Add(new ExecutionError($"Something went wrong Updating {countryInfoToUpdate.Name}"));
						return null;
					}
					// If all is good
					return countryInfoToUpdate;
				}
			);
			FieldAsync<CountryType>(
				Name="RemoveCountry",
				arguments: new QueryArguments(new QueryArgument<NonNullGraphType<IdGraphType>> { Name = "countryId" }),
				resolve: async context =>
				{
					var countryId = context.GetArgument<Guid>("countryId");

					var countryToDelete = await countryRepository.GetCountryAsync(countryId);

					// Country does not exist in db
					if (countryToDelete==null)
					{
						context.Errors.Add(new ExecutionError($"Country with ID {countryId} does not exist!"));
						return null;
					}

					// Check that country does not have a state or programmer associated with it
					var states = await countryRepository.GetStatesForCountryAsync(countryId);
					var programmers = await countryRepository.GetUsersForCountryAsync(countryId);
					if (states.Count() > 0 || programmers.Count() > 0)
					{
						context.Errors.Add(new ExecutionError($"{countryToDelete.Name} cannot be deleted as it's used by at least {programmers.Count()} programmers or {states.Count()} states!"));
						return null;
					}

					// At stage, we can delete the country
					if (!await countryRepository.DeleteCountryAsync(countryToDelete))
					{
						context.Errors.Add(new ExecutionError($"Something went wrong deleting {countryToDelete.Name}"));
						return null;
					}
					return countryToDelete;
				}
			);
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class SkillType : ObjectGraphType<Skill>
	{
		public SkillType()
		{
			Field(t => t.Id, type: typeof(IdGraphType)).Description("Id of Skill");
			Field(t => t.Name);
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Api.DbSeeds
{
	public static class DbSeeding
	{
		//public static void SeedDataContext(this CoderzoneApiDbContext coderzoneApiContext)
		public static void SeedDataContext(this CoderzoneApiDbContext coderzoneApiContext)
		{
			var user = new Programmer();
			//var hashedPwd = userManager.PasswordHasher.HashPassword(user, "<PASSWORD>");
			//userManager.CreateAsync(user, "adasdas");
			// Seed the database the country table is empty
			if (coderzoneApiContext.Countries.Count() == 0) {
				var hasher = new PasswordHasher<Programmer>();
				var countries = new List<Country>() {
					new Country()
					{
						Name = "Australia",
						States= new List<State>()
						{
							new State
							{
								Name ="QLD",
								PostCode ="4000",
								Programmer= new List<Programmer>()
								{
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "amenemope@2000",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Kelei",
											LastName = "Garwech",
											Avatar = "https://c1.sfdcstatic.com/content/dam/blogs/legacy/2014/05/6a00e54ee3905b883301a73dc2389e970.jpg",
											Bio = "I’m a software engineer in Santa Barbara, CA with a passion for computer science, electrical engineering and embedded systems technology.",
											City = "Brisbane",
											Street = "Tehuti Street",
											Number = 12,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = new DateTime(2019, 10, 7),
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Codebot Development",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The Codebots experiment is one of community-driven change and disruption. We're designing this awesome platform for you, so please keep hitting us up with your ideas and opinions",

												},
												new Project
												{
													Name ="Reactbot Development",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												},
												new Project
												{
													Name ="CSharpbot Testing",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="Delivering Codebots",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2019, 6, 7),
													EndDate = new DateTime(2019, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering Reactbot",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 7, 7),
													EndDate = new DateTime(2019, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering CSharpbot Testings",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of computer science", StartDate=new DateTime(2016,3,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Project Management", StartDate=new DateTime(2018,3,7),EndDate=new DateTime(2018,9,7), Description="Completed project management in software development in agile environment"},
												new Qualification{Title="Certificate of Database Design", StartDate=new DateTime(2019,7,7),EndDate=new DateTime(2019,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Cross-tier components implementation"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"},
												new Skill{Name="Strong analytical skills"},
												new Skill{Name="Document management"},
												new Skill{Name="Agile/Scrum"},
												new Skill{Name="Team player"},
												new Skill{Name="Testing"},
											}
										},
									},
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "amenpaleguangee@2000",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Okello",
											LastName = "Duany",
											Avatar = "https://flexxzone.fcmb.com/wp-content/uploads/2019/05/Entrepreneur-1.jpg",
											Bio = "I’m a software engineer in Santa Barbara, CA with a passion for computer science, electrical engineering and embedded systems technology.",
											City = "Brisbane",
											Street = "Tehuti Street",
											Number = 12,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = new DateTime(2019, 10, 7),
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Codebot Jinkin Deployment",
													ImageUrl ="https://codebots.com/site/img/icon-developing-a-continuous-learning-mindset.png",
													Description="Providing continuous learning opportunities for your employees, including opportunities around new technologies, practices and industry developments, strengthens your workforce to adapt quickly to a rapidly changing world",

												},
												new Project
												{
													Name ="Reactbot Feature Development",
													ImageUrl ="https://codebots.com/site/img/legacy-burdens_codebots-blog-thumbnail.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												},
												new Project
												{
													Name ="CSharpbot Selenium Testing",
													ImageUrl ="https://codebots.com/site/img/scaling-up-software-people-fit_codebots-blog-thumbnail.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="Delivering Codebots features",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2019, 4, 12),
													EndDate = new DateTime(2019, 6, 24)
												},
												new WorkExperience
												{
													Title="Delivering Reactbot Selenium Testing",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 8, 7),
													EndDate = new DateTime(2019, 9, 3)
												},
												new WorkExperience
												{
													Title="Delivering CSharpbot Testings",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of computer science", StartDate=new DateTime(2017,11,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Agile Management", StartDate=new DateTime(2017,8,7),EndDate=new DateTime(2018,9,7), Description="Completed project management in software development in agile environment"},
												new Qualification{Title="Advanced Database Design", StartDate=new DateTime(2019,7,7),EndDate=new DateTime(2019,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Cross-tier components implementation"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"},
												new Skill{Name="Strong analytical skills"},
												new Skill{Name="Document management"},
												new Skill{Name="Agile/Scrum"},
												new Skill{Name="Team player"},
												new Skill{Name="Testing"},
											}
										},
									}
								}
							},
							new State{
								Name ="NSW",
								PostCode ="3000",
								Programmer = new List<Programmer>(){
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "fm-luti@2003",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Fredie",
											LastName = "Luti",
											Avatar = "https://previews.123rf.com/images/olegdudko/olegdudko1507/olegdudko150712911/42641384-business-leadership-business-person-.jpg",
											Bio = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.",
											City = "Sydney",
											Street = "Chaatiem Street",
											Number = 112,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = new DateTime(2019, 3, 27),
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Targeted Innovation",
													ImageUrl ="https://xbsoftware.com/wp-content/uploads/2018/03/why-software-projects-can-take-tonger-than-planned-banner.png",
													Description="Lorem Ipsum is simply dummy text of the printing and typesetting industry.",

												},
												new Project
												{
													Name ="Data Driven Presentation",
													ImageUrl ="https://www.projectmanager.com/wp-content/uploads/2015/08/award-winning-project-management-software.png",
													Description="There are many variations of passages of Lorem Ipsum available",
												},
												new Project
												{
													Name ="Enterprise Integration and Coordination",
													ImageUrl ="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTsMIkTmxc_a_L3gcBFVBZfKX8Lacyk0fegAbvXZq1LFs-frj6h",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="Enterprise Integration and Coordination",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2019, 4, 12),
													EndDate = new DateTime(2019, 6, 24)
												},
												new WorkExperience
												{
													Title="Data Driven Presentation",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 8, 7),
													EndDate = new DateTime(2019, 9, 3)
												},
												new WorkExperience
												{
													Title="Targeted Innovation",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of computer science", StartDate=new DateTime(2017,11,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Agile Management", StartDate=new DateTime(2017,8,7),EndDate=new DateTime(2018,9,7), Description="Completed project management in software development in agile environment"},
												new Qualification{Title="Advanced Database Design", StartDate=new DateTime(2019,7,7),EndDate=new DateTime(2019,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Cross-tier components implementation"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"}
											}
										},
									},
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "annemoss",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Willam",
											LastName = "Kertzmann",
											Avatar = "https://i.vimeocdn.com/video/586907143.webp?mw=1100&mh=617&q=70",
											Bio = "I’m a software engineer in Santa Barbara, CA with a passion for computer science, electrical engineering and embedded systems technology.",
											City = "Sydney",
											Street = "Heru Street",
											Number = 312,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = DateTime.Now,
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Codebot Websocket",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The Codebots experiment is one of community-driven change and disruption. We're designing this awesome platform for you, so please keep hitting us up with your ideas and opinions",

												},
												new Project
												{
													Name ="Reactbot Websocket Templating",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												},
												new Project
												{
													Name ="CSharpbot Testing",
													ImageUrl ="https://codebots.com/site/img/20170327-codebots-logo-01.png",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="Delivering EGL Templates",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2018, 6, 7),
													EndDate = new DateTime(2018, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering Reactbot Form Behaviors",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2018, 7, 7),
													EndDate = new DateTime(2018, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering Form behaviors Testings",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of computer science", StartDate=new DateTime(2016,3,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Database Design", StartDate=new DateTime(2017,7,7),EndDate=new DateTime(2017,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"},
												new Skill{Name="Strong analytical skills"},
												new Skill{Name="Document management"},
												new Skill{Name="Agile/Scrum"},
												new Skill{Name="Team player"},
												new Skill{Name="Testing"},
											}
										},
									},
								}
							},
							new State{
								Name ="VIC",
								PostCode ="5000",
								Programmer = new List<Programmer>(){
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "fempto@2003",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Kerr",
											LastName = "Weychiang",
											Avatar = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyIB7a0XfyF7KoAYXiFxX7XCW1XsaqkGiT1lpjklEewDU9lXTa",
											Bio = "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
											City = "Melbourne",
											Street = "Nyaaruach Kulaang Street",
											Number = 111,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = new DateTime(2019, 8, 27),
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Total Innovation",
													ImageUrl ="https://www.veriday.com/wp-content/uploads/2017/11/ThinkstockPhotos-655567024-2.jpg",
													Description="Lorem Ipsum is simply dummy text of the printing and typesetting industry.",

												},
												new Project
												{
													Name ="Data Driven computers",
													ImageUrl ="https://i.ytimg.com/vi/2RKq4-GivBs/hqdefault.jpg",
													Description="There are many variations of passages of Lorem Ipsum available",
												},
												new Project
												{
													Name ="Artificial intelligence: Construction technology's next ",
													ImageUrl ="https://www.mckinsey.com/~/media/McKinsey/Industries/Capital%20Projects%20and%20Infrastructure/Our%20Insights/Artificial%20intelligence%20Construction%20technologys%20next%20frontier/Artificial-intelligence-construction_1_1536x1536.ashx",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="Enterprise Integration and Coordination",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2017, 8, 12),
													EndDate = new DateTime(2019, 6, 24)
												},
												new WorkExperience
												{
													Title="Data Driven Presentation",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 8, 7),
													EndDate = new DateTime(2019, 9, 3)
												},
												new WorkExperience
												{
													Title="Targeted Innovation",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of computer science", StartDate=new DateTime(2017,11,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Agile Management", StartDate=new DateTime(2017,8,7),EndDate=new DateTime(2018,9,7), Description="Completed project management in software development in agile environment"},
												new Qualification{Title="Advanced Database Design", StartDate=new DateTime(2019,7,7),EndDate=new DateTime(2019,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Cross-tier components implementation"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"}
											}
										},
									},
									new Programmer
									{
										Email = "<EMAIL>",
										UserName = "saibany@2012",
										PasswordHash =hasher.HashPassword(null,"<PASSWORD>"),
										Profile = new Profile
										{
											FirstName = "Manjooh",
											LastName = "Saibany",
											Avatar = "https://previews.123rf.com/images/kurhan/kurhan1210/kurhan121000190/15746938-business-people.jpg",
											Bio = "I’m a software engineer in Santa Barbara, CA with a passion for computer science, electrical engineering and embedded systems technology.",
											City = "Melboourne",
											Street = "Kuanywahr Street",
											Number = 22,
											CreatedAt = DateTime.Now,
											UpdatedAt = DateTime.Now,
											DatePublished = DateTime.Now,
											Projects = new List<Project>()
											{
												new Project
												{
													Name ="Chatbot groopon Zero",
													ImageUrl ="https://www.incimages.com/uploaded_files/image/970x450/getty_115809565_2000134320009280234_331152.jpg",
													Description="Side projects and side hustles can become million-dollar businesses. Just ask these folks",

												},
												new Project
												{
													Name ="Drupal React Plugins",
													ImageUrl ="https://cdn.mos.cms.futurecdn.net/8139da4ea227f62d005bf5c42837953c.jpg",
													Description="The real value of doing market research became clear when we realised we had missed something",
												},
												new Project
												{
													Name ="CSharpbot Selenium Testing Framework",
													ImageUrl ="https://www.aimdeliver.kiwi/wp-content/uploads/2014/04/technology-projects-rs.jpg",
													Description="The real value of doing market research became clear when we realised we had missed something",
												}
											},
											WorkExperiences = new List<WorkExperience>()
											{
												new WorkExperience
												{
													Title="React Mobx Integration",
													Description="For the past several weeks, our designers have been exploring the different directions we could take for the Codebots brand.",
													StartDate = new DateTime(2018, 6, 7),
													EndDate = new DateTime(2018, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering Reactbot Drupal Plugins",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2018, 7, 7),
													EndDate = new DateTime(2018, 10, 7)
												},
												new WorkExperience
												{
													Title="Delivering Selenium Testings Framework",
													Description="To test our favourite two logo designs, we surveyed more than 100 designers, developers, business owners, and tech enthusiasts to get their help.",
													StartDate = new DateTime(2019, 6, 18),
													EndDate = new DateTime(2019, 10, 7)
												}
											},
											Qualifications = new List<Qualification>()
											{
												new Qualification{ Title="BSc of Business computer science", StartDate=new DateTime(2016,3,7),EndDate=new DateTime(2019,10,7), Description="Completed software development"},
												new Qualification{Title="Diploma of Software IoT Design", StartDate=new DateTime(2017,7,7),EndDate=new DateTime(2017,10,5), Description="Completed a certificate of database design using MYSQL"},
											},
											Skills = new List<Skill>()
											{
												new Skill{Name="Technical design"},
												new Skill{Name="Quality assurance"},
												new Skill{Name="Capacity and scalability planning"},
												new Skill{Name="Optimising and performance tuning"},
												new Skill{Name="Strong analytical skills"},
												new Skill{Name="Document management"},
												new Skill{Name="Agile/Scrum"},
												new Skill{Name="Team player"},
												new Skill{Name="Testing"},
											}
										},
									},
								}
							}
						}
					}
				};

				// Save countries to the Database
				coderzoneApiContext.Countries.AddRange(countries);
				coderzoneApiContext.SaveChanges();
			}
		}
	}
}
<file_sep>﻿using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace CoderzoneGrapQLAPI.Migrations
{
    public partial class initial : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Countries",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Name = table.Column<string>(maxLength: 250, nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Countries", x => x.Id);
                });

            migrationBuilder.CreateTable(
                name: "States",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Name = table.Column<string>(maxLength: 100, nullable: false),
                    PostCode = table.Column<string>(nullable: true),
                    CountryId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_States", x => x.Id);
                    table.ForeignKey(
                        name: "FK_States_Countries_CountryId",
                        column: x => x.CountryId,
                        principalTable: "Countries",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "Programmers",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    UserName = table.Column<string>(nullable: true),
                    NormalizedUserName = table.Column<string>(nullable: true),
                    Email = table.Column<string>(nullable: true),
                    NormalizedEmail = table.Column<string>(nullable: true),
                    EmailConfirmed = table.Column<bool>(nullable: false),
                    SecurityStamp = table.Column<string>(nullable: true),
                    ConcurrencyStamp = table.Column<string>(nullable: true),
                    PhoneNumber = table.Column<string>(nullable: true),
                    PhoneNumberConfirmed = table.Column<bool>(nullable: false),
                    TwoFactorEnabled = table.Column<bool>(nullable: false),
                    LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
                    LockoutEnabled = table.Column<bool>(nullable: false),
                    AccessFailedCount = table.Column<int>(nullable: false),
                    PasswordHash = table.Column<string>(nullable: true),
                    StateId = table.Column<Guid>(nullable: true),
                    CountryId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Programmers", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Programmers_Countries_CountryId",
                        column: x => x.CountryId,
                        principalTable: "Countries",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Programmers_States_StateId",
                        column: x => x.StateId,
                        principalTable: "States",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "Profiles",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    FirstName = table.Column<string>(maxLength: 200, nullable: false),
                    LastName = table.Column<string>(maxLength: 200, nullable: false),
                    Avatar = table.Column<string>(nullable: true),
                    Bio = table.Column<string>(maxLength: 2000, nullable: false),
                    City = table.Column<string>(maxLength: 200, nullable: false),
                    Street = table.Column<string>(maxLength: 300, nullable: false),
                    Number = table.Column<int>(nullable: false),
                    DatePublished = table.Column<DateTime>(nullable: false),
                    CreatedAt = table.Column<DateTime>(nullable: false),
                    UpdatedAt = table.Column<DateTime>(nullable: false),
                    ProgrammerId = table.Column<Guid>(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Profiles", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Profiles_Programmers_ProgrammerId",
                        column: x => x.ProgrammerId,
                        principalTable: "Programmers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateTable(
                name: "Projects",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Name = table.Column<string>(maxLength: 200, nullable: false),
                    Description = table.Column<string>(maxLength: 2000, nullable: false),
                    ImageUrl = table.Column<string>(nullable: true),
                    ProgrammerId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Projects", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Projects_Programmers_ProgrammerId",
                        column: x => x.ProgrammerId,
                        principalTable: "Programmers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "Qualifications",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Title = table.Column<string>(maxLength: 200, nullable: false),
                    Description = table.Column<string>(maxLength: 2000, nullable: true),
                    StartDate = table.Column<DateTime>(nullable: false),
                    EndDate = table.Column<DateTime>(nullable: false),
                    ProgrammerId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Qualifications", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Qualifications_Programmers_ProgrammerId",
                        column: x => x.ProgrammerId,
                        principalTable: "Programmers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "Skills",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Name = table.Column<string>(maxLength: 200, nullable: false),
                    ProgrammerId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Skills", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Skills_Programmers_ProgrammerId",
                        column: x => x.ProgrammerId,
                        principalTable: "Programmers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateTable(
                name: "WorkExperiences",
                columns: table => new
                {
                    Id = table.Column<Guid>(nullable: false),
                    Title = table.Column<string>(maxLength: 200, nullable: false),
                    Description = table.Column<string>(maxLength: 2000, nullable: false),
                    StartDate = table.Column<DateTime>(nullable: false),
                    EndDate = table.Column<DateTime>(nullable: false),
                    ProgrammerId = table.Column<Guid>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_WorkExperiences", x => x.Id);
                    table.ForeignKey(
                        name: "FK_WorkExperiences_Programmers_ProgrammerId",
                        column: x => x.ProgrammerId,
                        principalTable: "Programmers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Profiles_ProgrammerId",
                table: "Profiles",
                column: "ProgrammerId",
                unique: true);

            migrationBuilder.CreateIndex(
                name: "IX_Programmers_CountryId",
                table: "Programmers",
                column: "CountryId");

            migrationBuilder.CreateIndex(
                name: "IX_Programmers_StateId",
                table: "Programmers",
                column: "StateId");

            migrationBuilder.CreateIndex(
                name: "IX_Projects_ProgrammerId",
                table: "Projects",
                column: "ProgrammerId");

            migrationBuilder.CreateIndex(
                name: "IX_Qualifications_ProgrammerId",
                table: "Qualifications",
                column: "ProgrammerId");

            migrationBuilder.CreateIndex(
                name: "IX_Skills_ProgrammerId",
                table: "Skills",
                column: "ProgrammerId");

            migrationBuilder.CreateIndex(
                name: "IX_States_CountryId",
                table: "States",
                column: "CountryId");

            migrationBuilder.CreateIndex(
                name: "IX_WorkExperiences_ProgrammerId",
                table: "WorkExperiences",
                column: "ProgrammerId");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Profiles");

            migrationBuilder.DropTable(
                name: "Projects");

            migrationBuilder.DropTable(
                name: "Qualifications");

            migrationBuilder.DropTable(
                name: "Skills");

            migrationBuilder.DropTable(
                name: "WorkExperiences");

            migrationBuilder.DropTable(
                name: "Programmers");

            migrationBuilder.DropTable(
                name: "States");

            migrationBuilder.DropTable(
                name: "Countries");
        }
    }
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface IProjectRepository
	{
		Task<IEnumerable<Project>> GetAllProjectsAsync();
		Task<ILookup<Guid, Project>> GetProjectsAsync(IEnumerable<Guid> programmerId);
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Models
{
	public class Project
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 5, ErrorMessage = "Project Name must be between 5 and 200 characters")]
		public string Name { get; set; }

		[Required]
		[StringLength(2000, MinimumLength = 50, ErrorMessage = "Description must be between 50 and 2000 characters")]
		public string Description { get; set; }

		public string ImageUrl { get; set; }
		//public Programmer Programmer { get; set; }
		public Profile Profile { get; set; }
		//public string[] TechStacks { get; set; }
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using GraphQL.DataLoader;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class ProgrammerType : ObjectGraphType<Programmer>
	{
		public ProgrammerType( 
			IProfileRepository profile, 
			IProjectRepository project, IProgrammerRepository programmer, 
			IDataLoaderContextAccessor dataLoaderAccessor)
		{
			Field(t => t.Id, type: typeof(IdGraphType)).Description("User Profile Id");
			Field(t => t.Email);
			Field(t => t.UserName);
			Field(t => t.PhoneNumber);
			Field<ProfileType>(
				name: "profile",
				resolve: context => profile.GetProgrammerProfileAsync(context.Source.Id)
			);
			Field<CountryType>(
				name: "country",
				resolve: context => programmer.GetCountryForProgrammerAsync(context.Source.Id)
				);
			Field<StateType>(
				name: "state",
				resolve: context => programmer.GetStateForProgrammerAsync(context.Source.Id)
			);
		}
	}
}
<file_sep>﻿using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class CountryInputType : InputObjectGraphType
	{
		public CountryInputType()
		{
			Name = "CountryInputType";
			Field<IdGraphType>("Id");
			Field<NonNullGraphType<StringGraphType>>("name");
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using GraphQL.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class StateType : ObjectGraphType<State>
	{
		public StateType()
		{
			Field(t => t.Id, type: typeof(IdGraphType)).Description("Id for State");
			Field(t => t.Name);
			Field(t => t.PostCode);
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface ICountryRepository
	{
		// READ OPERATIONS
		Task<IEnumerable<Country>> GetCountriesAsync();
		Task<Country> GetCountryAsync(Guid countryId);
		Task<Country> GetCountryOfUserAsync(Guid userId);
		Task<Country> GetCountryOfStateAsync(Guid stateId);
		Task<IEnumerable<Programmer>> GetUsersForCountryAsync(Guid countryId);
		Task<IEnumerable<State>> GetStatesForCountryAsync(Guid countryId);
		Task<bool> CountryExistsAsync(Guid countryId);
		Task<bool> IsDuplicateCountryNameAsync(Guid countryId, string countryName);

		// CREATE | UPDATE | DELETE OPERATIONS
		Task<bool> AddCountryAsync(Country country);
		Task<bool> UpdateCountryAsync(Country country);
		Task<bool> DeleteCountryAsync(Country country);
		Task<bool> SaveAsync();
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using CoderzoneGrapQLAPI.Services;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.EntityFramework;
using GraphQL.Types;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.controllers
{
	public class CodersGraphQLContext
	{
		public CoderzoneApiDbContext DbContext { get; set; }
	}

	[Route("[controller]")]
	public class GraphQLController : Controller
	{
		private readonly ISchema _schema;
		private readonly CoderzoneApiDbContext dbContext;
		private readonly IDocumentExecuter _documentExecuter;
		private readonly DataLoaderDocumentListener _dataLoaderListener;

		public GraphQLController(IDocumentExecuter documentExecuter, ISchema schema, CoderzoneApiDbContext dbContext, DataLoaderDocumentListener dataLoaderListener)
		{
			_schema = schema;
			this.dbContext = dbContext;
			_documentExecuter = documentExecuter;
			_dataLoaderListener = dataLoaderListener;
		}
		
		[HttpPost]
		public async Task<ExecutionResult> Post([FromBody] GraphQLQueryType query)
		{			
			if (!ModelState.IsValid || query == null)
			{
				throw new ArgumentNullException(nameof(query));
			}
	
			// construct query
			var executionOptions = new ExecutionOptions
			{
				Schema = _schema,
				Query = query.Query,
				OperationName = query.OperationName,
				Inputs = query.Variables?.ToInputs(),
				ExposeExceptions = true,
				EnableMetrics = true
			//UserContext = new CodersGraphQLContext
			//{
			//	DbContext = dbContext
			//}
		};

			executionOptions.Listeners.Add(_dataLoaderListener);
			// prepare the query for sending back to client
			var result = await _documentExecuter.ExecuteAsync(executionOptions);

			// check for errors
			if (result.Errors?.Count() > 0)
				Response.StatusCode = (int)HttpStatusCode.BadRequest;

			// send result back to client
			return result;
		}

	}
}




//[HttpPost]
//public async Task<IActionResult> Post([FromBody] GraphQLQueryType query)
//{
//	if (query == null)
//		throw new ArgumentNullException(nameof(query));
//	//var inputs = query.Variables?.ToInputs();

//	var executionOptions = new ExecutionOptions
//	{
//		Schema = _schema,
//		Query = query.Query,
//		//OperationName = query.OperationName,
//		Inputs = query.Variables?.ToInputs()
//	};
//	var result = await _documentExecuter.ExecuteAsync(executionOptions);
//	if (result.Errors?.Count > 0)
//		return BadRequest(result);

//	return Ok(result);
//}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using GraphQL.Types;

namespace CoderzoneGrapQLAPI.GraphQL.Types
{
	public class ProjectType: ObjectGraphType<Project>
	{
		public ProjectType()
		{
			Field(t => t.Id, type: typeof(IdGraphType)).Description("Id of Project");
			Field(t => t.Name);
			Field(t => t.Description);
			Field(t => t.ImageUrl);
		}
	}
}<file_sep>﻿using Microsoft.EntityFrameworkCore.Migrations;

namespace CoderzoneGrapQLAPI.Migrations
{
    public partial class profileupdatemigration : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(
                name: "FK_Projects_Programmers_ProgrammerId",
                table: "Projects");

            migrationBuilder.DropForeignKey(
                name: "FK_Qualifications_Programmers_ProgrammerId",
                table: "Qualifications");

            migrationBuilder.DropForeignKey(
                name: "FK_Skills_Programmers_ProgrammerId",
                table: "Skills");

            migrationBuilder.DropForeignKey(
                name: "FK_WorkExperiences_Programmers_ProgrammerId",
                table: "WorkExperiences");

            migrationBuilder.RenameColumn(
                name: "ProgrammerId",
                table: "WorkExperiences",
                newName: "ProfileId");

            migrationBuilder.RenameIndex(
                name: "IX_WorkExperiences_ProgrammerId",
                table: "WorkExperiences",
                newName: "IX_WorkExperiences_ProfileId");

            migrationBuilder.RenameColumn(
                name: "ProgrammerId",
                table: "Skills",
                newName: "ProfileId");

            migrationBuilder.RenameIndex(
                name: "IX_Skills_ProgrammerId",
                table: "Skills",
                newName: "IX_Skills_ProfileId");

            migrationBuilder.RenameColumn(
                name: "ProgrammerId",
                table: "Qualifications",
                newName: "ProfileId");

            migrationBuilder.RenameIndex(
                name: "IX_Qualifications_ProgrammerId",
                table: "Qualifications",
                newName: "IX_Qualifications_ProfileId");

            migrationBuilder.RenameColumn(
                name: "ProgrammerId",
                table: "Projects",
                newName: "ProfileId");

            migrationBuilder.RenameIndex(
                name: "IX_Projects_ProgrammerId",
                table: "Projects",
                newName: "IX_Projects_ProfileId");

            migrationBuilder.AddForeignKey(
                name: "FK_Projects_Profiles_ProfileId",
                table: "Projects",
                column: "ProfileId",
                principalTable: "Profiles",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_Qualifications_Profiles_ProfileId",
                table: "Qualifications",
                column: "ProfileId",
                principalTable: "Profiles",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_Skills_Profiles_ProfileId",
                table: "Skills",
                column: "ProfileId",
                principalTable: "Profiles",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_WorkExperiences_Profiles_ProfileId",
                table: "WorkExperiences",
                column: "ProfileId",
                principalTable: "Profiles",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropForeignKey(
                name: "FK_Projects_Profiles_ProfileId",
                table: "Projects");

            migrationBuilder.DropForeignKey(
                name: "FK_Qualifications_Profiles_ProfileId",
                table: "Qualifications");

            migrationBuilder.DropForeignKey(
                name: "FK_Skills_Profiles_ProfileId",
                table: "Skills");

            migrationBuilder.DropForeignKey(
                name: "FK_WorkExperiences_Profiles_ProfileId",
                table: "WorkExperiences");

            migrationBuilder.RenameColumn(
                name: "ProfileId",
                table: "WorkExperiences",
                newName: "ProgrammerId");

            migrationBuilder.RenameIndex(
                name: "IX_WorkExperiences_ProfileId",
                table: "WorkExperiences",
                newName: "IX_WorkExperiences_ProgrammerId");

            migrationBuilder.RenameColumn(
                name: "ProfileId",
                table: "Skills",
                newName: "ProgrammerId");

            migrationBuilder.RenameIndex(
                name: "IX_Skills_ProfileId",
                table: "Skills",
                newName: "IX_Skills_ProgrammerId");

            migrationBuilder.RenameColumn(
                name: "ProfileId",
                table: "Qualifications",
                newName: "ProgrammerId");

            migrationBuilder.RenameIndex(
                name: "IX_Qualifications_ProfileId",
                table: "Qualifications",
                newName: "IX_Qualifications_ProgrammerId");

            migrationBuilder.RenameColumn(
                name: "ProfileId",
                table: "Projects",
                newName: "ProgrammerId");

            migrationBuilder.RenameIndex(
                name: "IX_Projects_ProfileId",
                table: "Projects",
                newName: "IX_Projects_ProgrammerId");

            migrationBuilder.AddForeignKey(
                name: "FK_Projects_Programmers_ProgrammerId",
                table: "Projects",
                column: "ProgrammerId",
                principalTable: "Programmers",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_Qualifications_Programmers_ProgrammerId",
                table: "Qualifications",
                column: "ProgrammerId",
                principalTable: "Programmers",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_Skills_Programmers_ProgrammerId",
                table: "Skills",
                column: "ProgrammerId",
                principalTable: "Programmers",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);

            migrationBuilder.AddForeignKey(
                name: "FK_WorkExperiences_Programmers_ProgrammerId",
                table: "WorkExperiences",
                column: "ProgrammerId",
                principalTable: "Programmers",
                principalColumn: "Id",
                onDelete: ReferentialAction.Restrict);
        }
    }
}
<file_sep>﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CoderzoneGrapQLAPI.Models;

namespace CoderzoneGrapQLAPI.Services
{
	public class ProfileRepository : IProfileRepository
	{
		private readonly CoderzoneApiDbContext _profileContext;
		public ProfileRepository(CoderzoneApiDbContext profileContext)
		{
			_profileContext = profileContext;
		}
		public Task<IEnumerable<Profile>> GetAllProfilesAsync()
		{
			// Fetch all profiles
			return Task.FromResult(_profileContext.Profiles.AsEnumerable());
		}

		public Task<Profile> GetProgrammerProfileAsync(Guid programmerId)
		{
			// Empty programmerId field
			if (programmerId == Guid.Empty) throw new ArgumentNullException(nameof(programmerId));

			// Fetch the programmer's profile
			return Task.FromResult(_profileContext.Profiles.FirstOrDefault(p => p.ProgrammerId == programmerId));
		}

		public Task<bool> ProgrammerProfileExistsAsync(Guid profileId)
		{
			// bookId is null or empty
			if (profileId == Guid.Empty) throw new ArgumentNullException(nameof(profileId));

			// Return true if author with authorId exists
			return Task.FromResult(_profileContext.Profiles.Any(a => a.Id == profileId));
		}

		public Task<IEnumerable<Project>> GetAllProjectsByProgrammerAsync(Guid profileId)
		{
			// Fetch all Projects from programmer
			return Task.FromResult(_profileContext.Projects.Where(p => p.Profile.Id == profileId).AsEnumerable());
		}

		public Task<IEnumerable<Qualification>> GetAllQualificationsByProgrammerAsync(Guid profileId)
		{
			// Fetch all Qualification from programmer
			return Task.FromResult(_profileContext.Qualifications.Where(q => q.Profile.Id == profileId).AsEnumerable());
		}

		public Task<IEnumerable<Skill>> GetAllSkillsByProgrammerAsync(Guid profileId)
		{
			// Fetch all Qualification from programmer
			return Task.FromResult(_profileContext.Skills.Where(q => q.Profile.Id == profileId).AsEnumerable());
		}

		public Task<IEnumerable<WorkExperience>> GetAllWorkExperiencesByProgrammerAsync(Guid profileId)
		{
			// Fetch all Work Experience from programmer
			return Task.FromResult(_profileContext.WorkExperiences.Where(w => w.Profile.Id == profileId).AsEnumerable());
		}

		public Task<ILookup<Guid, Project>> GetAllProjectsAsync(IEnumerable<Guid> profileIds)
		{
			var reviews = _profileContext.Projects.Where(p => profileIds.Contains(p.Profile.Id)).ToLookup(r => r.Id);

			var projects = _profileContext.Projects.Where(p => profileIds.Contains(p.Profile.Id)).ToLookup(r => r.Profile.Id);
			//return Task.FromResult(_programmerContext.Projects.Where(p => programmerId.Contains(p.Programmer.Id)).ToLookup(r => r.Programmer.Id));
			return Task.FromResult(projects);
		}

		public async Task<IDictionary<Guid, Project>> GetProjectsAsync(IEnumerable<Guid> profileIds, CancellationToken token)
		{
			var reviews = _profileContext.Projects.Where(p => profileIds.Contains(p.Profile.Id)).ToDictionary(x => x);
			//return await Task.FromResult<Dictionary<Guid, Project>>(reviews);
			var taskResults = await Task.FromResult<IDictionary<Guid, Project>>(_profileContext.Projects.Where(p => profileIds.Contains(p.Profile.Id)).ToDictionary(p => p.Id));

			return taskResults; // Task.FromResult(taskResults);
		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public class CoderzoneApiDbContext : DbContext
	{
		public CoderzoneApiDbContext(DbContextOptions<CoderzoneApiDbContext> options) : base(options)
		{
			// run migration at app starts
			Database.Migrate();
		}

		// Tell EF what tables what tables it need to set up
		public virtual DbSet<Profile> Profiles { get; set; }
		public virtual DbSet<Country> Countries { get; set; }
		public virtual DbSet<State> States { get; set; }
		public virtual DbSet<Skill> Skills { get; set; }
		public virtual DbSet<Project> Projects { get; set; }
		public virtual DbSet<Qualification> Qualifications { get; set; }
		public virtual DbSet<WorkExperience> WorkExperiences { get; set; }
		public virtual DbSet<Programmer> Programmers { get; set; }
		//public virtual DbSet<Recommendation> Recommendation { get; set; }

		// Set up many to many relationships if needed
		protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
			modelBuilder
				.Entity<Programmer>()
				.HasOne(c => c.Profile)
				.WithOne(p => p.Programmer);

			modelBuilder
				.Entity<Profile>()
				.HasOne(c => c.Programmer)
				.WithOne(p => p.Profile)
				.HasForeignKey<Profile>(p => p.ProgrammerId);

		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoderzoneGrapQLAPI.Models;

namespace CoderzoneGrapQLAPI.Services
{
	public class ProjectRepository : IProjectRepository
	{
		public readonly CoderzoneApiDbContext _projectContext;
		public ProjectRepository(CoderzoneApiDbContext projectContext)
		{
			_projectContext = projectContext;
		}

		

		public Task<IEnumerable<Project>> GetAllProjectsAsync()
		{
			throw new NotImplementedException();
		}

		public async Task<ILookup<Guid, Project>> GetProjectsAsync(IEnumerable<Guid> programmerId)
		{
			var reviews = _projectContext.Projects.Where(a => programmerId.Contains(a.Profile.Id)).ToAsyncEnumerable();
			return await reviews.ToLookup(r => r.Profile.Id);
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace CoderzoneGrapQLAPI.Models
{
	public class Profile
	{
		[Key]
		public Guid Id { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 2, ErrorMessage = "First Name must be between 2 and 200 characters")]
		public string FirstName { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 2, ErrorMessage = "Last Name must be between 2 and 200 characters")]
		public string LastName { get; set; }

		public string Avatar { get; set; }

		[Required]
		[StringLength(2000, MinimumLength = 50, ErrorMessage = "Bio must be between 50 and 2000 characters")]
		public string Bio { get; set; }

		[Required]
		[StringLength(200, MinimumLength = 5, ErrorMessage = "City Name must be between 5 and 200 characters")]
		public string City { get; set; }

		[Required]
		[StringLength(300, MinimumLength = 5, ErrorMessage = "Street Name must be between 5 and 300 characters")]
		public string Street { get; set; }

		[Required]
		public int Number { get; set; }

		[DataType(DataType.Date)]
		public DateTime DatePublished { get; set; }

		[DataType(DataType.Date)]
		public DateTime CreatedAt { get; set; }

		[DataType(DataType.Date)]
		public DateTime UpdatedAt { get; set; }
		public Guid ProgrammerId { get; set; }
		public Programmer Programmer { get; set; }

		public virtual ICollection<Project> Projects { get; set; }
		public virtual ICollection<WorkExperience> WorkExperiences { get; set; }
		public virtual ICollection<Qualification> Qualifications { get; set; }
		public virtual ICollection<Skill> Skills { get; set; }
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoderzoneGrapQLAPI.Api.DbSeeds;
using CoderzoneGrapQLAPI.GraphQL;
using CoderzoneGrapQLAPI.Services;
using CoderzoneGrapQLAPI.Api.Middlewares;
using GraphiQl;
using GraphQL;
using GraphQL.Http;
using GraphQL.Server;
using GraphQL.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using CoderzoneGrapQLAPI.GraphQL.Types;
using GraphQL.DataLoader;
using GraphQL.Execution;
using CoderzoneGrapQLAPI.GraphQL.Mutations;

namespace CoderzoneGrapQLAPI
{
	public class Startup
	{
		public IHostingEnvironment _env { get; set; }
		public static IConfiguration Configuration { get; set; }

		//public Startup(IConfiguration configuration) { }
		public Startup(IHostingEnvironment env, IConfiguration configuration)
		{
			_env = env;
			Configuration = configuration;
		}


		// This method gets called by the runtime. Use this method to add services to the container.
		// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
		public void ConfigureServices(IServiceCollection services)
		{
			// add mvc if needed
			services.AddMvc();

			// Setup DB Connections
			services.AddDbContext<CoderzoneApiDbContext>(options => options.UseSqlServer(Configuration["connectionStrings:CoderzoneDbConnectionString"]));

			// Register Users Repository

			// Register Profile Repository

			// Register Country Repository
			services.AddScoped<ICountryRepository, CountryRepository>();
			services.AddScoped<ICountryRepository, CountryRepository>();
			services.AddScoped<IProgrammerRepository, ProgrammerRepository>();
			services.AddScoped<IProfileRepository, ProfileRepository>();
			services.AddScoped<IProjectRepository, ProjectRepository>();
			//services.AddScoped<IStateRepository, StateRepository>();

			//services.AddSingleton<ICountryRepository, CountryRepository>();


			// Register State Repository

			// Register GraphQL			
			services.AddSingleton<IDocumentExecuter, DocumentExecuter>();
			services.AddSingleton<CoderzoneApiQuery>();
			services.AddSingleton<CoderzoneApiMutation>();
			services.AddSingleton<CountryType>();
			services.AddSingleton<CountryInputType>();
			services.AddSingleton<StateType>();
			services.AddSingleton<ProgrammerType>();
			services.AddSingleton<ProfileType>();
			services.AddSingleton<SkillType>();
			services.AddSingleton<WorkExperienceType>();
			services.AddSingleton<QualificationType>();
			services.AddSingleton<ProjectType>();

			// Add GraphQLexpose developmet exceptions
			//services.AddSingleton<IDocumentWriter, DocumentWriter>();
			//services.AddSingleton<IDataLoaderContextAccessor, DataLoaderContextAccessor>();
			services.AddSingleton<IDataLoaderContextAccessor>(new DataLoaderContextAccessor());
			//services.AddSingleton<IDocumentExecutionListener, DataLoaderDocumentListener>();
			services.AddSingleton<DataLoaderDocumentListener>();

			services.AddGraphQL(o => { o.EnableMetrics = true; o.ExposeExceptions = _env.IsDevelopment(); })
					.AddGraphTypes(ServiceLifetime.Singleton)
					.AddDataLoader();

			//Register GraphQL resolver
			//services.AddScoped<IDependencyResolver>(
			//	provider => new FuncDependencyResolver(provider.GetRequiredService)
			//);

			var sp = services.BuildServiceProvider();
			services.AddSingleton<ISchema>(new CoderzoneApiSchema(new FuncDependencyResolver(type => sp.GetService(type))));
			//
			//services.AddSingleton<ISchema, CoderzoneApiSchema>();
			//Register GraphQL Schema
			//services.AddScoped<CoderzoneApiSchema>();
			//services.AddScoped<CoderzoneApiSchema>();

		}

		// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
		public void Configure(IApplicationBuilder app, IHostingEnvironment env, CoderzoneApiDbContext context)
		{
			if (env.IsDevelopment())
			{
				app.UseDeveloperExceptionPage();
			}

			// set up cors
			app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());

			// use graphQL passing in the schema
			app.UseGraphiQl();

			//app.UseGraphQL<CoderzoneApiSchema>();
			//app.GraphQLMiddleware<CoderzoneApiSchema>();

			// set up as MVC if necessary
			app.UseMvc();

			// Seed the database
			context.SeedDataContext();


		}
	}
}
<file_sep>﻿using CoderzoneGrapQLAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace CoderzoneGrapQLAPI.Services
{
	public interface IProgrammerRepository
	{
		Task<IEnumerable<Programmer>> GetProgrammersAsync();
		Task<Programmer> GetProgrammerAsync(Guid programmerId);
		Task<Country> GetCountryForProgrammerAsync(Guid programmerId);
		Task<State> GetStateForProgrammerAsync(Guid programmerId);
		Task<bool> ProgrammerExistsAsync(Guid programmerId);
	}
}