Advanced Debugging With Visual Studio 2019 And OzCode

Debugging is the most tricky and challenging part of the software development process. Some bugs or problems are really hard to find because of a combination of different technologies, making it hard to find the root cause of the problem. For example, if you want to load a sequence of records from the database in reactive programming style: think of all the layers/abstractions you can have between the caller and the result; Rx, Threads, LINQ, EF, EF-Provider, .NET, SQL Server engine, Windows, etc. If any problem happened while acquiring the data, in most cases, it is easy to figure out the problem, but sometimes investigating the issue is very hard and costs a lot of time, money, and requires expertise.
 
In this article, I have described the magical debugging tool, OzCode, which helps you debug complex applications, and can save a lot of investigation time. You might also need a good tracing/logging tool and a good design/strategy for error handling, and remember: the tools alone cannot help you to solve the complex problems.
 
Now let’s get started,
 

Prerequisites

  1. Download and Install the visual studio preview version.

    Note
    I have tested with VS 2019 Preview and VS 2017

  2. Downloading and Installing the OzCode.

Visual Studio 2019

 
I love VS2019 because there are a lot of enhancements everywhere! My favorite new feature is the text search in the Watch window.
 
 
    The new search textbox
    The search depth: The scan depth of the search-algorithm in the object graph
    The result windows
The excellent news is this feature has already existed in OzCode for the past couple of years, and is even more useful: not only can you use it to do advanced searches – you can also filter the results, and it is also significantly faster. OzCode is an interactive debugging tool which helps you at the runtime to find and fix the bugs.
 
The figure below shows the Free Text search in OzCode. 
 
 
    The text to be searched = “Customer”
    Founded items
   Search depth   
 
I have used OzCode, and I want to share my experience with it, and knowledge about it.
 

OzCode

 
Exception handling
 
If you are a programmer, then you know that the root exception is not always clear. When an exception happens in your method and if it is not caught, then the code flow will be stopped and redirected (exit) from the current method to the previous. This technique is known as exception propagation. Again, exception propagation is a process in which the exception is dropped from to the top to the bottom of the calling stack and into the calling chain is not handled there, the exception again drops down to the previous method, and so on until it gets caught or until it reaches the very bottom of the call stack. If the exception remains uncaught even after reaching the bottom of the stack, then the application is terminated.
 
In many cases, these exceptions are handled, aggregated, redirected or converted to another kind of exception (and then rethrown), attaching the original exception in an InnerException, in the best-case scenario.
 
OzCode allows a quick move to inner exceptions and predicting exceptions before they happened and it helping you find the root problem in a very gentle and modern way.
 
To demonstrate that, I have created a demo application in GitHub to test OzCode, and while developing the demo application, I have got my first exception as shown below.
 
 
Or download the source code from here.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
As you see above in the icon Advanced Debugging With Visual Studio 2019 And OzCode that was one exception (not nested/aggregated). Moreover, I have clicked on the exception icon. Then the below Window will appear.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
As shown above, I have searched for the solution in the google without copying or pasting anything.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
I have taken the first Google website.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
Amazing! I recognize what the problem is and how can I solve it with three mouse clicks!
 
I have tested with many different problems, and I can see the root exceptions very quickly.
 

Advanced Debugging

 
Finding specific information in the Visual Studio Debug Windows (Watch Window) is one of the most common problems that we have faced in the past. My workaround for the problem was: I have copied and pasted the debugger-results to Excel or Notepad++ and searched the desired information in Excel/Notepad++, then OzCode made my life easy - let’s see how everything works.
 
I have created a mini shop application for this demo and seeded it with some data. I have used .NET Core/ EF Core /SQL Server.
 
I have posted down the POCO classes and the data seeding, to help you understand the data structures.
  1. public class Product {  
  2.  public int ProductId {  
  3.   get;  
  4.   set;  
  5.  }  
  6.   
  7.  public string Name {  
  8.   get;  
  9.   set;  
  10.  } = string.Empty;  
  11.   
  12.  public string Description {  
  13.   get;  
  14.   set;  
  15.  } = string.Empty;  
  16.   
  17.  public double Price {  
  18.   get;  
  19.   set;  
  20.  }  
  21. }  
  22.   
  23. public class Admin {  
  24.  public int AdminId {  
  25.   get;  
  26.   set;  
  27.  }  
  28.   
  29.  public string Name {  
  30.   get;  
  31.   set;  
  32.  } = string.Empty;  
  33. }  
  34.   
  35. public class Customer {  
  36.  public int CustomerId {  
  37.   get;  
  38.   set;  
  39.  }  
  40.   
  41.  public string Name {  
  42.   get;  
  43.   set;  
  44.  } = string.Empty;  
  45.   
  46.  public ICollection < Order > Orders {  
  47.   get;  
  48.   set;  
  49.  } = new Collection < Order > ();  
  50. }  
  51.   
  52. public class Order {  
  53.  public int OrderId {  
  54.   get;  
  55.   set;  
  56.  }  
  57.   
  58.  public int Quantity {  
  59.   get;  
  60.   set;  
  61.  }  
  62.   
  63.  public Customer Customer {  
  64.   get;  
  65.   set;  
  66.  } = new Customer();  
  67.   
  68.  public Product Product {  
  69.   get;  
  70.   set;  
  71.  } = new Product();  
  72. }  
  73.   
  74. public class Shop {  
  75.  public int ShopId {  
  76.   get;  
  77.   set;  
  78.  }  
  79.   
  80.  public ICollection < Admin > Admins {  
  81.   get;  
  82.   set;  
  83.  } = new Collection < Admin > ();  
  84.   
  85.  public ICollection < Customer > Customers {  
  86.   get;  
  87.   set;  
  88.  } = new Collection < Customer > ();  
  89.   
  90.  public ICollection < Product > Products {  
  91.   get;  
  92.   set;  
  93.  } = new Collection < Product > ();  
  94. }  
I have seeded my shop - database as following:
  1. public class DatabaseSeeding {  
  2.  public void CreateAndSeed() {  
  3.   using(var dbContext = new ShopDbContext()) {  
  4.    // Generating the database  
  5.    dbContext.Database.EnsureDeleted();  
  6.    dbContext.Database.EnsureCreated();  
  7.   
  8.    // Adding Products  
  9.    const int productCount = 30;  
  10.    var products = new Product[productCount];  
  11.    for (var i = 0; i < productCount; i++) {  
  12.     var product = new Product {  
  13.      Description = $ "Description {i}", Name = $ "Product Name {i}", Price = i  
  14.     };  
  15.     dbContext.Products.Add(product);  
  16.     products[i] = product;  
  17.     // Store inside the loop to simulate a sequential data storing.  
  18.     dbContext.SaveChanges();  
  19.    }  
  20.   
  21.    var admin = new Admin {  
  22.     Name = "Admin"  
  23.    };  
  24.   
  25.    var customer1 = new Customer {  
  26.     Name = "Customer 1"  
  27.    };  
  28.    var customer2 = new Customer {  
  29.     Name = "Customer 2"  
  30.    };  
  31.    var customer3 = new Customer {  
  32.     Name = "Customer 3"  
  33.    };  
  34.   
  35.    // Adding Customers  
  36.    dbContext.Customers.Add(customer1);  
  37.    dbContext.Customers.Add(customer2);  
  38.    dbContext.Customers.Add(customer3);  
  39.    dbContext.Admins.Add(admin);  
  40.    dbContext.SaveChanges();  
  41.   
  42.    // Adding Shop  
  43.    var shop = new Shop {  
  44.     Products = products  
  45.    };  
  46.    shop.Customers.Add(customer1);  
  47.    shop.Customers.Add(customer2);  
  48.    shop.Customers.Add(customer3);  
  49.    shop.Admins.Add(admin);  
  50.   
  51.    dbContext.Shops.Add(shop);  
  52.    dbContext.SaveChanges();  
  53.   
  54.    for (var i = 0; i < 10; i++) {  
  55.     var order = new Order {  
  56.      Product = products[i], Customer = customer1, Quantity = 1  
  57.     };  
  58.     dbContext.Orders.Add(order);  
  59.     // Store inside the loop to simulate a sequential data storing.  
  60.     dbContext.SaveChanges();  
  61.    }  
  62.   
  63.    for (var i = 10; i < 20; i++) {  
  64.     var order = new Order {  
  65.      Product = products[i], Customer = customer2, Quantity = 2  
  66.     };  
  67.     dbContext.Orders.Add(order);  
  68.     // Store inside the loop to simulate a sequential data storing.  
  69.     dbContext.SaveChanges();  
  70.    }  
  71.   
  72.    for (var i = 20; i < productCount; i++) {  
  73.     var order = new Order {  
  74.      Product = products[i], Customer = customer3, Quantity = 3  
  75.     };  
  76.     dbContext.Orders.Add(order);  
  77.     // Store inside the loop to simulate a sequential data storing.  
  78.     dbContext.SaveChanges();  
  79.    }  
  80.   }  
  81.  }  

Shop Database

 
Shop Table
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
 
 
 
 
 
 
Customers Table
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
 
 
 
 
 
 
Products Table
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Orders Table
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

My first Query

 
I have made a complex query: flattening all orders, taking only the orders that have a Quantity between two and three, then skipping two orders and then taking five orders.
  1. private static void FiveOrders() {  
  2.  using(var dbContext = new ShopDbContext()) {  
  3.   var shopQuery = dbContext.Shops.Include(x => x.Products)  
  4.    .Include(x => x.Admins)  
  5.    .Include(x => x.Customers)  
  6.    .ThenInclude(x => x.Orders);  
  7.   
  8.   var firstOrders = shopQuery  
  9.    .SelectMany(c => c.Customers)  
  10.    .SelectMany(o => o.Orders)  
  11.    .Where(s => s.Quantity > 1)  
  12.    .Skip(2)  
  13.    .Take(15)  
  14.    .OrderByDescending(x => x.OrderId);  
  15.   
  16.   foreach(var order in firstOrders) {  
  17.    Console.WriteLine(order);  
  18.   }  
  19.  }  
  20. }  
I have put a breakpoint on the query and started the application. If you look at the breakpoint , you can see everywhere the question mark icons; that'w because the query is still now not evaluated (IQueryable).
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
Nothing unusual until now, but how can you evaluate and investigate an IQueryable? to do that, I have added ToList() to execute the shop query as shown below:
 
Advanced Debugging With Visual Studio 2019 And OzCode 
 
As you see, something magical is happening. ToList() has loaded all entries from the database (!Do not use this trick in the production code! This kills your application performance), and with this trick, I can evaluate the query in memory so that I can debug it step by step and watch the data flow:
 
I have clicked on 1/1 icon then OzCode Debug Window is opened as shown above .
 
Count = 3  shows how many customers contain the Customers collection.
 
I have clicked on the lambda icon () To open the LINQ analysis window, showing me the LINQ query in a graphical style. Once you understand how this works, it can save you a lot of time and help you debug even the most complex LINQ queries.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
As shown below, I have clicked on SelectMany() and then opened the Customer Collection().
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
The left Window () show the customer-collection before executing SelectMany(), and the right Window ( ) is showing the result of SelectMany().
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
As shown above, I have selected the second SelectMany(), and then I have chosen the first customer. As you see in the right Window, the Orders (light pink colored  ) belong to the first customer (with CustomerId =1).
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
I have clicked on the Where-Clause  in the left Window. Now, you can see in the left Window, which items are excluded from the Where-Clause , and in the right Window , you can see the result after executing the Where-Clause.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
The Skip before and after executing is shown above  (Maroon line).
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
Above is the Take operation  .
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
Finally, The OrderBy Desc operation  . Look to the lines above, WOW!
 

Trace

 
As I told you before, to make a good, successful application that works, you need an excellent debugging and tracing tool too. When one developer lost a few hours because of missing searching/filtering/sorting functionality in their tracing tool, this might cost the same as a yearly subscription for an excellent tracing tool with filters and search- that could have saved that time (If you are saving money in the developers tools, then you are trying to save money in the wrong place!).
 
OzCode offers a smart tracing technique which can help you trace the multi-threading application and other use cases very well. I also like the SmartInspect.
 
I have added a Trace Point at line 3:
  1. private static void TraceOrders() {  
  2.  for (var i = 1; i < 10; i++) {  
  3.   Console.WriteLine(GetOrder(i));    
  4.  }  
  5. }  
  6.   
  7. private static Order GetOrder(int orderId) {  
  8.  using(var dbContext = new ShopDbContext()) {  
  9.   var ordersQuery = dbContext.Orders.Include(x => x.Customer).Include(x => x.Product);  
  10.   return ordersQuery.Single(x => x.OrderId == orderId);  
  11.  }  
  12. }  
I have modified the Expression, as shown below.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
I have executed the code, and you can see the Order Id.
 
Advanced Debugging With Visual Studio 2019 And OzCode 
 
You can also set a filter, for example, a filter on the Time, see below. 
 
Advanced Debugging With Visual Studio 2019 And OzCode
 

Compare Objects on Graph Objects

 
You can compare two objects or collection as follows.
 
In the Customers query, select the first Order from the Query.
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
Then select the second object from the collection (any other Order).
 
Advanced Debugging With Visual Studio 2019 And OzCode
 
The result: The differences are shown in Compare Window.
 
Advanced Debugging With Visual Studio 2019 And OzCode

Summary

Visual Studio 2019 has many new debug enhancements, and OzCode is complementary to VS2019 debugging tools which makes the debugging process more comfortable and save a lot of developers time.
 
OzCode has a lot of more exciting features which I did not mention in this article. The next article is depending on your comments.
 
I can write about:
  • More OzCode features
  • Debugging with WinDbg
  • Cloud Debugging
Thank you! I appreciate you for reading my article.


Similar Articles