private static async Task Run(IReadOnlyList <string> Arguments) { // Configure JSON.NET and Refit. _httpClient = new HttpClient(new CacheBustingMessageHandler()) { BaseAddress = new Uri(_mappingServiceUrlBase) }; _jsonSerializer = new JsonSerializer(); _mappingService = RestService.For <IMappingService>(_httpClient); JsonConvert.DefaultSettings = () => new JsonSerializerSettings { // Preserve case of property names. ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver(), // Preserve cyclical object references. PreserveReferencesHandling = PreserveReferencesHandling.All }; Func <Task <GetOpenServiceCallsResponse> > getOpenServiceCalls = ParseCommandLine(Arguments); do { // Call web service using specified function, then verify object references are preserved. Stopwatch stopwatch = Stopwatch.StartNew(); GetOpenServiceCallsResponse response = await getOpenServiceCalls(); stopwatch.Stop(); Console.WriteLine($"Retrieved {response.ServiceCalls.Count} service calls, {response.Customers.Count} customers, and {response.Technicians.Count} technicians in {stopwatch.Elapsed.TotalSeconds:0.000} seconds."); VerifyObjectReferencesPreserved(response); } while (string.IsNullOrWhiteSpace(Console.ReadLine())); }
public async Task <GetOpenServiceCallsResponse> GetOpenServiceCallsAsync() { var response = new GetOpenServiceCallsResponse(); // Each row in SQL result represents a unique service call but may contain duplicate customers and technicians. const string sql = @"select sc.Id, sc.Scheduled, sc.[Open], c.Id, c.Name, c.Address, c.City, c.State, c.ZipCode, t.Id, t.Name from ServiceCalls sc inner join Customers c on sc.CustomerId = c.Id inner join Technicians t on sc.TechnicianId = t.Id where sc.[Open] = 1"; using (var connection = new SqlConnection(_appSettings.Database)) { await connection.OpenAsync(); await connection.QueryAsync <ServiceCall, Customer, Technician, ServiceCall>(sql, (ServiceCall, Customer, Technician) => { // This lambda method runs once per row in SQL result. response.ServiceCalls.Add(ServiceCall); // Reference existing customers and technicians or add to collection if first time encountered. if (!response.Customers.TryGetValue(Customer.Id, out var customer)) { // Customer mapped by Dapper not in collection. customer = Customer; response.Customers.Add(customer); } if (!response.Technicians.TryGetValue(Technician.Id, out var technician)) { // Technician mapped by Dapper not in collection. technician = Technician; response.Technicians.Add(technician); } // Configure relationships among objects. ServiceCall.Customer = customer; ServiceCall.Technician = technician; customer.ServiceCalls.Add(ServiceCall); if (!customer.Technicians.Contains(technician.Id)) { // Technician not found in customer's collection. customer.Technicians.Add(technician); } technician.ServiceCalls.Add(ServiceCall); if (!technician.Customers.Contains(customer.Id)) { // Customer not found in technician's collection. technician.Customers.Add(customer); } return(null); }); } return(response); }
private static void VerifyObjectReferencesPreserved(GetOpenServiceCallsResponse Response) { const int technicianId = 3276; const int customerId = 75904; const int serviceCallId = 8949862; var technician = Response.Technicians[technicianId]; var customer = Response.Customers[customerId]; var serviceCall = Response.ServiceCalls[serviceCallId]; Trace.Assert(ReferenceEquals(technician, customer.Technicians[technicianId])); Trace.Assert(ReferenceEquals(technician, serviceCall.Technician)); Trace.Assert(ReferenceEquals(customer, technician.Customers[customerId])); Trace.Assert(ReferenceEquals(customer, serviceCall.Customer)); Trace.Assert(ReferenceEquals(serviceCall, technician.ServiceCalls[serviceCallId])); Trace.Assert(ReferenceEquals(serviceCall, customer.ServiceCalls[serviceCallId])); }