In an earlier tip, I discussed how the OfType operator lets you run LINQ queries against collections that don't otherwise support LINQ. One reader of that column pointed out that, under the hood, a function named Cast was doing all the work. Another reader pointed out that what's special about OfType and Cast is that, unlike the other LINQ keywords, they work with collections that aren't generic types. Instead, OfType and Cast allow you to specify the type of the objects in the collection.
As an example of how to use Cast and OfType, imagine an ArrayList holding nothing but Customer objects:
Dim customers As New ArrayList
Both Cast and OfType will let you issue LINQ queries against the collection:
Dim custs = From c In customers.Cast(Of Customer)()
Where c.CreditLimit = 0
Dim custs = From c In customers.OfType(Of Customer)()
Where c.CreditLimit = 0
But what if the ArrayList contains a variety of objects? This collection contains both DeadbeatCustomer and PremiumCustomers:
Either Cast or OfType will let you work with this collection of diverse objects, but in very different ways. OfType will extract the objects of a specific type, so this example will process only the DeadbeatCustomer objects in the collection:
Dim custs = From c In customers.OfType(Of DeadbeatCustomer)()
Where c.CreditLimit = 0
Cast, on the other hand, will let you work with all items in the collection, provided they share an interface (i.e., inherit from some common base object or implement a common interface). This example assumes that both DeadbeatCustomer and PremiumCustomer interfaces both implement an interface named IBuyer:
Dim custs = From c In customers.Cast(Of IBuyer)()
Where c.CreditLimit = 0
So thanks, guys: This was your column. I'll send you a bill for writing it up.
Posted by Peter Vogel on 02/04/2014 at 3:23 AM0 comments
I didn't know this until my fellow instructor at Learning Tree (and author of Learning Tree's ASP.NET Web Forms course), Kevin Rattan, pointed it out to me: when you trigger validation at the server by calling the Validate method, you can pass the name of a Validation Group to the method. When you do, only those Validators you've assigned to that group (through the Validators' ValidationGroup property) will execute.
This allows you to check parts of your page for problems, and if you find a problem, skip validating the rest of the page. If you're using the UpdatePanel, you can trigger validation just for the controls in the panel that was posted back to the server.
Posted by Peter Vogel on 01/31/2014 at 7:45 AM0 comments
In an earlier tip, I suggested that in five or 10 minutes, you could set up a source control system for yourself by using Subversion; but what if you're part of a team? Even if every team member has their own source control in place (doubtful), you still want some central repository that represents your "gold" code. There is a simple solution and it's free, provided your project has five or fewer members: Team Foundation Service (Team Foundation Server in the cloud). While the TFS team says TFS will work with any editor, TFS integrates especially well with Visual Studio 2012 and 2013. If you're using Visual Studio 2010, you can still use TFS: just follow these steps, which includes installing a quick patch.
With TFS, you not only get cloud-based source control, you also get a central location to keep track of your team's work items (tasks and features), plus virtual meeting rooms if you're not all within driving distance of each other. Of course, if you get too dependent on TFS and add a sixth member to your team, you might have to buy one of Microsoft's plans or export your code and find a new provider.
Posted by Peter Vogel on 01/27/2014 at 9:16 AM0 comments
A surprising number of Visual Basic programmers (i.e., more than one) aren't aware of a feature unique to their language: Project-level Imports. Namespaces added to the list of project-level Imports are, effectively, automatically added to the code files that make up your application --there's no need to add Import statements to the top of the code file for those namespaces.
You can add or remove project-level Imports by opening your Project's properties (right-click on the project in Solution Explorer and select Properties) and selecting the References tab. The list of project-level Imports appears at the bottom of the resulting form. Adding a namespace there means that you don't have to include it in your code file.
There is a wrinkle with using project-level Imports, however: If you remove the libraries whose namespaces are referenced in the Imports, your application will stop compiling. You'll need to track those Imports down and delete them. The good news here is that, instead of those Imports being scattered through your code files, they're all in one place -- though, perhaps, not an obvious place.
Posted by Peter Vogel on 01/23/2014 at 9:04 AM0 comments
I like Windows Presentation Foundation (WPF) very much, especially its implementation of the Model-View-Controller (MVC) design pattern. I've also grown to appreciate XAML as a declarative (if quirky) way of building complex user interfaces that integrate with a testable code file. However, every once in a while, I end up with a WPF Window that takes a long time to render, or renders in a bizarre series of jumps. If that's happened to you, it's worthwhile to download Microsoft's WPF Performance Suite.
The suite includes two tools: Perforator and Visual Profiler. Neither will tell you what to do to fix your problem, but both will help you locate the problem.
Perforator concentrates on the low-level routines that render your XAML. The download page for the package includes some useful information about the kind of values you should see with Perforator to help you figure out where your problem is. You can also experiment with various settings to see which (if any) will help with your problem.
While Perforator looks at how WPF is rendering your XAML, Visual Profiler shows how individual controls you've included in your XAML (Buttons, Lines and so on) are being rendered. In many ways, this is more useful to the developer: once you know what your problem controls are, you can focus on what's causing them to behave badly. The best solution may be to just do without them.
Posted by Peter Vogel on 01/13/2014 at 12:42 PM0 comments
The ability to nest one class inside provides a powerful way to encapsulate code inside a class to organize complex functionality used within a single class. A nested class looks like this:
Public Class MyClass
…code for the class…
Public Sub SomeMethod()
Dim mnc As MyNestedClass
mnc = New MyNestedClass()
…using the nested class…
As the example shows, in the surrounding host class you can instantiate the nested class and use it. No other class, however, can access the nested class. Nested classes give you a way of organizing the functionality of the host class without exposing that functionality to other classes (or cluttering up your IntelliSense lists with new classes that are only useful in one place -- the host class).
For instance, in a recent application, I needed to manage the permissions and privileges for three levels of users in a form. I created a class for each type of user, with each class holding all (and only) the code for managing what that type of user was allowed to do. Any permissions-related code that was shared by all the users I put in a base class that the three user classes inherited from, giving me four classes altogether. This design cleaned up and organized my permissions code while simplifying the code in the host that set permissions in the form's user interface: the host class just instantiated the right nested class and called its permissions-related members.
Since these classes were only relevant to that single form, I nested all four classes within the controller for that form. With that design, code in the form could instantiate the nested classes and use their members, but the classes didn't appear in any IntelliSense lists outside of the host class.
If you do need to make a nested class available to the outside world, you can add a property to your host class that returns the nested class (as I did in a recent column on creating a fluent interface).
And, of course, you can argue that any class that needs nested classes is too big and too complicated, and is probably violating the Single Responsibility Principle. But that's a different discussion.
Posted by Peter Vogel on 01/09/2014 at 2:32 PM0 comments
If you miss the free version of Reflector now that Red Gate's taken it over, and if you don't appreciate the functionality that Red Gate has added to it, then ILSpy is for you.
ILSpy will decompile any .NET DLL back to either Visual Basic or C# (your choice), and provide a viewer that lets you browse the results. If you want to find out how the code behind the framework DLLs works (or if you've just lost your source code), ILSpy will let you see it. There are even a few plugins for ILSpy that enhance the basic package (and they're also free).
ILSpy doesn't provide the tight integration with Visual Studio (and Visual Studio debugging) that Red Gate's Reflector does, but -- did I mention this? -- it won't cost you a dime.
Posted by Peter Vogel on 01/08/2014 at 1:17 PM0 comments
Over a series of articles about commenting, I discussed why the key issue is to write ROC (Really Obvious Code). If you do, then the only comments you need to provide for your methods should be what parameters the method expects, what your method will do with those parameters, what the method will return, and any side effects of executing the method (e.g., database updates). If you bought into that plan (and some readers did not), then the best place to put that documentation is where Visual Studio will make the best use of it: in IntelliSense, by using XML comments.
To create the structure for your XML comments, click your mouse before your method declaration; then, in Visual Basic, type three apostrophes ('''); in C#, type three forward slashes (///). In either case, Visual Studio will add a framework to hold the comments for your method, for each of the parameters the method accepts, and for your method's return value (if any). All you have to do is type in your content.
Not only will the programmers who work on your code find all the information they need when changing your code, the developers who use your methods will find that IntelliSense delivers your documentation to them when they use your methods.
Posted by Peter Vogel on 01/07/2014 at 9:23 AM0 comments
You're working with a variable, property, method or class and you need more information about it. If you hover your mouse over the item's name, IntelliSense displays the information for you. But when you need more information or, especially, if you want to make some changes to the item, clicking on the item's name and pressing F12 will take you to it.
When you're done making your changes, you probably want to go back to that original code. Pressing Control_- (<Ctrl> minus) will take you there (officially known as navigate backward or BrowsePrevious). If Control_- doesn't take you back to where you want to go immediately, it's only because it will stop at some other places where you rested between when you pressed F12 and where you are now. Just keep pressing Control_- and you'll eventually get back to where you want to be.
Posted by Peter Vogel on 12/09/2013 at 7:23 AM0 comments
Like everyone else, I like code-first Entity Framework (EF) development because it makes it so easy to integrate custom code with my EF entity code. But even in a pure code-first development, I suspect that most developers don't generate their databases from their entities because, most of the time, the database already exists (and, besides, the DBA won't let developers anywhere near the database's schema). That means you have to write all the repetitious property declaration in the entity objects to mimic the tables you'll be working with. Wouldn't it be nice if you had a tool to do it for you?
There are POCO generators out there, but you already have a tool: the ADO.NET Entity Framework database-first designer. The original versions of the designer generated a lot of peculiar code. More recent versions generate code that looks very much like the code you should write when doing code-first development. Why not take advantage of that?
Start by adding a new project to your solution. Then, to get the cleanest entity code possible, use NuGet to add Entity Framework 6.0 to the project. From Project | Add New Item, add the ADO.NET Entity Data Model and use the Wizard to work through adding the tables needed for your project. When you're done, close the designer to ensure that all the code for your entities is generated.
Now drill down beneath your edmx file in Solution Explorer to find your code files. You can skip the file called <NameOfYourModel>.cs/vb and <NameOfYourModel>.Designer.cs/vb (though, since the files have nothing in them, there's probably no harm in including them). Once you've found the files, still in Solution Explorer, drag them to your "real" data access project. Whenever you need to add another table you can return to the project with the designer and use it to generate your code for you.
This isn't a perfect solution: The edmx generator in EF 6.0 doesn't add any data annotations to the entities it generates, for instance (recently, I needed to add the Key attribute to the primary key properties on a project). This solution is also easier to implement in Visual Basic than in C# because of the embedded namespaces in the C# files. Even in C#, though, a project-wide search-and-replace will fix that problem. But by using a tool from the EF team to generate your EF code, you're guaranteed to be getting the best (and most up-to-date) EF code possible.
Posted by Peter Vogel on 12/04/2013 at 8:22 AM0 comments
I've been working on a Windows Forms application for one of my clients and, in the application, I use the CheckedBoxList and the DataGridView. Both of them have really useful collections: the CheckedBoxList has a CheckedItems collection that holds all the items that the user has checked, and the DataGridView has a SelectedRows collection that holds all the rows the user's selected, for instance. The CheckedItems collection can hold any object I want while the SelectedRows collection holds DataGridViewRow objects.
The problem is that neither of these collections will work with LINQ.
Fortunately, rather than use For…Each loops, I can use the OfType method to convert these collections into something that will work with LINQ. All I have to do is pass the OfType method the object type held in the collection. For instance, to use LINQ with the DataGridView's SelectedRows collection, I use this code; it converts the DataItem property for each row into the object associated with each row:
Dim coll = From rw In Me.gvInvoices.SelectedRows.OfType(Of DataGridViewRow)()
Select CType(rw.DataBoundItem, ClaimCededDetailClass
The following code processes the ClaimHeaderClass objects I hold in my CheckedBoxList, and hands back those object that have their AuthorizationLevel property set to "High":
Dim cc = cblClaims.CheckedItems.OfType(Of ClaimHeaderClass).
Where(Function(chc) chc.AuthorizationLevel = "High")
But wait, there's more! I have a Panel on the form with a set of RadioButtons in it. The Panel, of course, has a Controls collection that holds all of those RadioButtons. This code converts that collection into a LINQ-compatible collection of RadioButtons, then lets me find the name of the RadioButton the user selected:
strRadio = (From rb In Me.plStatusRadio.Controls.OfType(Of RadioButton)()
Posted by Peter Vogel on 11/15/2013 at 7:52 PM0 comments
About a year ago, Patrick Steele did a great job of describing AutoMapper: an absolutely necessary tool if you're using Data Transfer Objects to move data between parts of your application. AutoMapper will automatically move data from your business entities into the corresponding properties on your DTO, saving you many, many lines of repetitious assignment statements. It also means that if you add a new property to your DTO, AutoMapper will automatically pick up the corresponding property from the entity; no further changes to your code required.
You do need to be careful, however, when moving your data from a DTO and into an Entity Framework (EF) entity object. By default, AutoMapper creates a new instance of the object that the data is being moved into. If you write code like the following, for instance, the Customer object in custExisting that's returned from AutoMapper is a different object from the Customer object retrieved from the DbContext (even though the custExisting variable points to both of those objects):
Mapper.CreateMap(Of CustomerDTO, Customer)()
custExisting = dbs.Customers.Single(Function(c) c.Id = custDTO.Id)
custExisting = Mapper.Map(Of CustomerDTO, Customer)(custDTO)
That's bad, because EF won't track the changes made to that new custExisting object: When you call SaveChanges, nothing will be saved back to the database. This is a common-enough problem that there's even some misinformation about it floating around. I've seen a couple of forums, for instance, where people with this problem have been told that AutoMapper can't be used to update entities.
You can update entities with AutoMapper. Here's how: pass both the DTO and the entity object to AutoMapper's Map method. That's what this code does:
custExisting = Mapper.Map(Of CustomerDTO, Customer)(custDTO, custExisting)
Rather than creating a new entity object to return from the Map method, AutoMapper now updates the entity object passed in the second parameter and returns it to my custExisting variable. As a result, EF will track the changes made to the entity object; and, when you call SaveChanges, your updates will be sent to the database.
Posted by Peter Vogel on 11/06/2013 at 7:53 AM0 comments