Including the Location of Your Error in Your Error Message

A user calls you to complain that your code has thrown an exception. You ask the user to read the message to you … and you realize that you have no idea where that error comes from. You would know if you'd included the Exception object's TargetSite property in your error message because that property reports on the method that had the problem.

The TargetSite property returns a MethodBase object (part of .NET's Reflection infrastructure) which has a ton of properties telling you everything you'd ever want to know about the method. However, all you probably want in your error message is the method's full name, including the name of the class. To get that, just call the TargetSite's ToString method:

Try
  ' ... potential exception
Catch ex As Exception
  Throw New Exception("Something has gone horribly wrong at " & ex.TargetSite.ToString)
End Try

One caveat: If you're still embedding class and method names in your ASP.NET MVC routing rules then the class name/method name is information you probably don't want to share with your users (though you still might want to write those names to some log). Fortunately, I discussed how to avoid embedding controller and method names in your UI in my previous tip which makes that problem go away.

Posted by Peter Vogel on 07/22/2016 at 4:47 PM0 comments


Write to Visual Studio's Output Window on Your Breakpoints

I can't tell you the number of times I've put a breakpoint inside a loop so that I could stop each time I go through the loop and check the value of some variable or property. Unfortunately, by the third or fourth trip through the loop I've forgotten what the values were on my first trip through the loop.

If that's your life also, your best choice is to use a tracepoint which will write the information you're interested in to the output window. With a tracepoint, you can review the values you're interested in after the loop finishes. You can even just let your code run, rather than stopping on the line you're interested in.

Setting a tracepoint varies from one version of Visual Studio to another. The easiest way is to set a breakpoint and then right click on the dot in the margin that marks your breakpoint. When the popup menu appears, either select the When Hit choice (in earlier versions of Visual Studio) or the Actions choice (in later versions). Those choices will display the dialog that lets you define your tracepoint.

In that dialog you can enter the message you want written to the output window, enclosing any variables you want displayed in curly braces ({ }). Something like "The counter is {i} and the Customer's age is {cust.age}" will work, for example.

If you'd rather not stop on the breakpoint, make sure the Continue Execution checkbox at the bottom of the dialog is checked. You can do a quick visual check to see if you'll be stopping on the line: If you still have a dot in the margin, it's still a breakpoint and you'll stop every time the line is hit; if you have a diamond in the margin, it's a tracepoint and will just write out your message without pausing.

Now run your application and, after it finishes, look in the output window to see how your data changed over time.

Posted by Peter Vogel on 06/23/2016 at 11:40 AM0 comments


Save Some Time Deleting Entities in Entity Framework: RemoveRange

When it comes to speeding up your application, your best opportunity is to reduce trips to your database. So, when you see a method like RemoveRange on a DbContext collection, you might think that's an opportunity to delete a bunch of objects in less time than deleting those same objects one by one. You'd be right…but not because you're saving trips to your database.

Here's some sample code that will delete all of the SalesOrderHeaders with a DueDate before the current date:

Dim res = From so In db.SalesOrderHeaders 
          Where so.DueDate < DateTime.Now 
          Select so 
db.SalesOrderHeaders.RemoveRange(res)  
db.SaveChanges

This will run faster than, for example, looping through the res collection and passing each object to the SalesOrderHeaders Remove method before calling SaveChanges. However, either way, you'll still be making one trip to the database, submitting one SQL delete statement for every SalesOrderHeader that's being deleted.

Where you'll save time is in the overhead around removing the objects from the SalesOrderHeaders collection (especially around change tracking which will run once with RemoveRange rather than once for each object with Remove).

Posted by Peter Vogel on 06/21/2016 at 12:56 PM0 comments


Save a Trip to the Database with Deletes in Entity Framework

In both deletes and updates there's an assumption that you have to retrieve the corresponding entity object from the database. With an update, you pull back the object so that you can set its properties; with a delete, you retrieve the object so that you can pass it to the corresponding collection's Remove method. That delete code might look like this, for example:

Dim cust As Customer
cust = db.Customers.Find("A123")
db.Customers.Remove(cust)
db.SaveChanges

You don't have to actually need to make that first trip to the database. For a delete, for example, all you have to do is convince Entity Framework's change tracking mechanism that you've deleted the object ... and that just means that you have to remove an object with the right values in the primary key properties. This code, for example:

Dim cust As New Customer
cust.CustId = "A123"
db.Customers.Attach(cust)
db.Customers.Remove(cust)
db.SaveChanges()

will delete Customer A123 from the database without having to retrieve it.

Posted by Peter Vogel on 06/03/2016 at 12:33 PM0 comments


Convert a List from One Type to Another

You have a List of one object but you really want to have a List of some other object. If it was a single object, you could cast from one to the other with a single line of code:

Dim pCust As PremiumCustomer = New PremiumCustomer
Dim cust As Customer 
cust = pCust

But, because you have a collection of objects, you might assume that you have to write a loop and transfer your objects from one List to the other individually. The good news is that you can do that in one line of code using two LINQ functions: Cast and ToList. Here's the one line solution that creates a list of Customers from a list of a derived class, PremiumCustomers:

Dim pCusts As List(Of CustomerPremium) pCusts = GetPremiumCustomers()
Dim custs As List(Of Customer)
custs = pCusts.Cast(Of Customer)().ToList()

Unlike some "clever" LINQ solutions this one is, I think, actually readable. Under the hood, of course, that loop is probably still being created by LINQ and the compiler…but you don't have to write it. Besides, with this single line of code, the compiler might even be able to invoke some clever optimization to speed up the process.

I didn't come up with this myself: If you're interested there are six more useful LINQ tips where this one came from, all thanks to Igor Ostrovsky.

Posted by Peter Vogel on 06/01/2016 at 11:51 AM0 comments


Organize Classes into Folders in Class View

It doesn't show often in the columns I write here, but I'm a big fan of organizing large projects into files. You can, of course, create those folders in Solution Explorer, which adds the folders to your file system.

But, if you use Class View, you know that your Solution Explorer folders don't show up there. As the number of classes in your application starts to increase, the usefulness of Class View starts to diminish. If you want, though, you can also organize Class View into folders … and those folders don't have to match your Solution View folders.

It's not obvious how to do this -- right-clicking in Class View and picking Add from the submenu won't give you a folder option, for example. Instead, you need to click the Add Folder button in the top left-hand corner of Class View. Once you've created your folder, you can drag classes into it (still in Class View, of course). You can also create subfolders (right-clicking on a folder will give you a New Folder option).

These folders only exist in your solution's information file (the .sou file) and aren't added to your file system.

Posted by Peter Vogel on 05/20/2016 at 1:03 PM0 comments


Changing Parameter Values with out and ref

By default, any values that you pass to a method in a parameter are protected from change inside the method. In this code, for example, I know that my variable NotChanged can't be different after I call the method. In this code, the test on the last line is guaranteed to be true:

string NotChanged;
NotChanged = "Fred";
MyOrdinaryMethod(NotChanged);
if (NotChanged == "Fred") ...

That is, unless the parameters to the method are marked with the ref keyword, as in this example:

void MyRefMethod(ref string parm1)
{

Now, if I call this method the value of anything that I pass to that first parameter could be different after calling the method. To make sure that I realize that possibility, the compiler also requires that the calling code use the ref keywords. In this code, the test on the last line is not guaranteed to be true and, thanks to having to provide the ref keyword, I know that:

string PossiblyChanged;
PossiblyChanged = "Fred";
MyRefMethod(ref res);
if (PossiblyChanged == "Fred") ...

While a parameter marked with the ref keyword may or may not be changed, the out keyword is more definite: The out keyword indicates that code inside the method will always change the value in the parameter. If you mark a parameter as out and there is a path through your method that doesn't alter the value of the parameter then the compiler will generate an error.

In addition, with the out parameter, the compiler will refuse to compile your method if, inside your method, you attempt to use the out parameter without first setting its value. In other words, when calling a method with an out parameter, the calling code can set the value of the parameter before passing it to the method -- but it won't do a bit of good because the method has to override that value before it can use the parameter. Again, because I have to use the out parameter when calling the method, I know that:

string DefinitelyChanged;
MyRefMethod(out DefinitelyChanged);
if (DefinitelyChanged == "Fred") ...

That's it for now, I'm out.

Posted by Peter Vogel on 05/05/2016 at 9:37 AM0 comments


Set Culture Information in One Step in .NET Framework 4.5

In the .NET Framework 4.0 or earlier, you have to set the culture for each thread individually. At the very least, this meant setting the CurrentThread object's CurrentCulture and CurrentUICulture properties. In the .NET Framework 4.5, you can do it in just two lines of code for every thread in your application, using the CultureInfo object.

The syntax is a little "un-obvious": You must first instantiate a CultureInfo object, passing a culture code. You then pass that object to a static method called DefaultThreadCurrentCulture, also on the CultureInfo object.

Typical code looks like this:

Dim ci As CultureInfo
ci = New CultureInfo("en-CA")
CultureInfo.DefaultThreadCurrentCulture = ci

which sets the culture code for all threads to English/Canadian.

Posted by Peter Vogel on 05/03/2016 at 10:19 AM0 comments


Get the Path to Your File in Visual Studio

One of the best things about Solution Explorer is that I can right-click on a Project, pick "Open Folder in File Explorer" and, a second later, I'm in Windows Explorer, able to work with the files that make up the project. This also works with Solutions or, really, any folder displayed in Solution Explorer (for example, if you have Show All Files turned on, you can use this with the bin folder or obj folders).

Often, however, I'm not focused on the Project (or Solution) as a whole: I'm interested in one specific file -- usually, the one that I have open in my editor window. When that's the case, I can just right-click on the file's editor tab and select "Open Containing Folder." This not only opens the appropriate folder in Windows Explorer, it also selects and highlights the file I'm interested in.

Posted by Peter Vogel on 04/21/2016 at 12:22 PM0 comments


Organizing Visual Studio Project Templates

Visual Studio has lots of templates but you probably use only a few of them. Why not create your own area with all (and only) the templates you actually use?

It’s easy to do: First, shut down Visual Studio. Then, open Windows Explorer and surf to the folder that holds your templates. This folder can move around a lot. For Visual Studio 2015 Community Edition on my computer, it’s at C:\Users\<username>\Documents\Visual Studio 2015\Templates\ProjectTemplates. For Visual Studio 2012 and earlier, I’d recommend looking in the area of C:\Program Files (x86)\Microsoft Visual Studio<version>Common7\IDE. If you can’t find the folder, probably the simplest solution is just to do a search for the ProjectTemplates folder from Windows Explorer.

Once you’ve found the ProjectTemplates folder, add your own subfolder within it and copy the templates you want from the other subfolders into your new folder.

After you’re done with that, make sure your computer is plugged in, your battery charged, and open the Visual Studio command prompt. In the command prompt type:

devenv.com /installvstemplates

One caveat: For Visual Studio 2015, I also had to navigate down to Common7/IDE before entering the command. Now press Enter and wait.

Microsoft stresses that it’s critical that you let this command run to completion, which is why it’s a good idea to make sure you won’t run out of power part way through. When the command finishes (when the prompt reappears in the command window), open Visual Studio and go to your project list. You should find your new area with the templates you selected in the project templates list.

Posted by Peter Vogel on 04/07/2016 at 12:10 PM0 comments


Step Out of Debugging To, Well, Wherever You Want

When you're debugging, you probably know that you can use the Debug | Step Out menu choice to exit a method without having to step through all the code in the method. But, if you want to step out and back to some higher-level method, you can do that also by using the Call Stack.

If you're not displaying the Call Stack window when stopped at your breakpoint, go to the Debug menu and select Windows | Call Stack. When the window appears, right click on the method where you want to stop again and select "Run to cursor" to continue executing until you get back to that method.

The first time you use this technique is a bit of a pain because you probably don't have the Call Stack window open. After you've used it the first time, however, the window will be right there waiting for you the next time you need it.

Posted by Peter Vogel on 04/01/2016 at 11:58 AM0 comments


Supporting LINQ Queries Calling Your Methods

You have a method like this that returns a collection of premium Customer objects:

Public Function GetPremiumCustomers() As List(of Customer)
  Dim db As New dbContextObject
  Return From c In db.Customers
         Where c.IsPremium = True
         Select c
End Function

The problem is that other developers will want to use your method to further refine this query:

res = (From c in GetPremiumCustomers()
       Where c.City = "Regina"
       Select c).ToList()

If you're not careful the GetPremiumCustomers will retrieve every premium customer when the developer using your method only wants some of the premium customers (the ones in Regina). Retrieving more data than you'll ever want is a sure way to slow down your application. Wouldn't it be great if the LINQ query inside your method could be combined with the LINQ query using your method when the SQL statement is generated?

You can give .NET the opportunity to do exactly that -- to collapse both queries into a single SQL statement that retrieves only the premium customers from Regina -- if you just declare your GetPremiumCustomers method as returning the IQueryable interface. All you need to do is write your function's signature:

Public Function GetPremiumCustomers() As IQueryable(of Customer)
  Return From c In db.Customers
         Where c.IsPremium = True
         Select c

to return a result of IQueryable.

Posted by Peter Vogel on 03/16/2016 at 12:07 PM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.