Defining Natural Keys in Entity Framework Entity Classes

It's not something database developers do much anymore, but it is possible to have a primary key in a table that isn't generated by the database. If you do have a key like that, here's what you have to do: when writing an entity class in Entity Framework, you need to tell Entity Framework about it by flagging the corresponding property in the entity class. You do that by decorating the property with the DatabaseGenerated attribute and specifying a DatabaseGeneratedOption.

For a key not generated by the database, the option to pick is DatabaseGeneratedOption.None, like this:

 Public  Class SalesOrder
<Key(), DatabaseGenerated(DatabaseGeneratedOption.None)> Public Property SalesOrderId As Integer

Posted by Peter Vogel on 05/19/2014 at 12:32 PM0 comments


Speed Up Entity Framework Startup

Before your first query against an Entity Framework (EF) model, EF gathers data about your database based on the entities and relationships you've defined to EF; then EF does it again before your first save. If you have lots of entities and relationships in your model, the information-gathering phase can take awhile. Just to make it worse: doubling the number of entities in a model seems to more than double the time in the information-gathering phase. Let's not ask how I know this.

Entity Framework Power Tools can help here by gathering that information at design time, rather than at run time. Depending on how many entities and relationships you have, you can see order of magnitude improvements on your first query and save (literally: reducing the time to execute the first query or save by 10 to 100 times).

To generate this data at design time, first install Power Tools through Visual Studio's Tools | Extension Manager menu choice. With that installed, find the file containing your DbContext object, right-click it, then select Entity Framework | Generate Views. You'll end up with a new file with the same name as your context class file, but with "Views" inserted before the file type (e.g., NorthwindContext.Views.cs). Some caveats: Your DbContext class must have at least one constructor that doesn't require parameters; your project must compile; and your EF classes must be valid (check Visual Studio's Output window for messages from Power Tools if you don't get the Views file).

But nothing is free: If you make a change that affects how your application stores or updates tables either to your database schema or to your model's configuration, your application will blow up because your design time Views code no longer matches the reality of your database. To avoid this, you'll need to test your application when you make a change that might conflict with the code in your Views file. If it turns out that you have a problem, you must regenerate the Views file and redeploy your application. That's a pain, so you'll only want to use this technique if that first query and save is really hurting your performance.

Another option is to not generate the Views file at all. This step is only necessary if you have a lot of tables and relationships in your model, so a better solution is to not have a lot of tables and relationships in your model. Your first step should be to consider ways to limit the size of your EF model (see my earlier tip on bounded models). But if you can't do that and your performance is unacceptable, Views may give you the relief you need.

Posted by Peter Vogel on 05/01/2014 at 11:32 AM0 comments


Free Tool: Convert C# to Visual Basic or Visual Basic to C#

I recently got some feedback from readers about using Visual Basic rather than C# for the sample code in my Practical .NET column. Ironically, the feedback came just before I started doing a whole bunch of columns with code in C# (the columns are about Entity Framework 6 and I used Entity Framework Power Tools to generate my entity code; sadly, Power Tools for Entity Framework 6 is still in beta and only produces C# code).

But that feedback got me looking for a good conversion tool, and eventually I found one at Telerik. Copy your code, surf to the site, paste your code in the top window, set the direction of the conversion (the default is C# to VB), click the button, and copy your converted code from the bottom window. You're now a dual-language warrior.

But I didn't use that tool in my columns. Honest. I wrote all the code myself. At least, that's the basis I'm using for billing my time.

Posted by Peter Vogel on 04/25/2014 at 8:06 AM0 comments


Limiting Your Entity Framework Models

If you're not reading Julie Lerman's Data Points column over at MSDN Magazine, you're missing out (in fact, I just realized that my recent column and her column are almost the same, except that hers covers more stuff). I especially appreciated her columns on Domain-Driven Design. And those columns got me thinking about where I should put my Entity Framework (EF) code.

The problem with code-first EF is writing out all the properties in all the entity classes and then applying the customizations those classes need. It's a lot of work: you don't want to do that more than once for any entity. And once you've got the entity built, its code may well be useful in other applications: you want to re-use.  It's tempting strategy to package up all of your entity code and your DbContext class in a class library that you can copy from project to project.

The problem with that strategy is that, over time, that class library is going to contain references to every table and relationship in your organization's database. Because of that, your program is going to stop dead the first time you issue a query or call SaveChanges, as EF gathers information about all those tables and relationships (I have a partial solution to that problem coming up in another tip).

But, as Julie suggests in her Domain-Driven Design columns, your applications should use bounded domains: your application should just be using the entities that your application needs. And that led me to think about how to share my EF code while avoiding the performance hit. I realized, for example, that the performance hit isn't related to how many entities I've defined -- it's related to how many entities I've referenced in my DbContext object.

It seems to me that the class library I'm copying from one project to another should contain just the code that defines my entities (i.e., I should think of it as a strategic resource). My DbContext object, on the other hand, should be defined in my application and just reference the entities my application needs (it should be a tactical resource).

There are obviously some wrinkles here. Navigation properties that reference other entities are one example: If you include one entity in your DbContext object, you'll need to include all of the entities those navigation properties reference… and pretty soon all your entities are back in your DbContext object. Another example: EF 6's custom configurations (see my column on using them to make Complex Types useful). Like your entities, those customizations are both a lot of work, and because they're part of an entity's definition, something that should be treated as a strategic resource.

For navigation properties, partial classes may be the solution. First, define the DbContext object in the application, referencing just the entities you need. Second, define the entities in partial classes in a class library that's shared among applications; where necessary, this class library will also hold methods to configure these entities (these methods will accept a ModelBuilder object). Third, in your application, add partial classes for the entities you're using, but use these classes to define the navigation properties your application needs (and only those properties). Finally: also in your application, in your DbContext's OnModelCreating method, call out to those methods that configure the entities you need. You'll be able to reuse your entities with their configurations and still have a bounded domain that will load as fast as it can.

This sounds promising. I'll try it out in my next project (provided that I can get my client on board, of course. Or maybe not: what they don't know won't hurt me).

Posted by Peter Vogel on 04/21/2014 at 9:10 AM0 comments


Stacking Up Error Handlers in ASP.NET

If you add multiple HandleError attributes to an ASP.NET MVC Controller method or class, each HandleError can target a specific exception and send the user a different View. The following example assigns custom Views to two exceptions (ArithmeticException and DivideByZeroException). For any other Exception, the user is sent the default Error View:

<HandleError(exceptiontype:=GetType(DivideByZeroException), Order:=99, View:="UserError")>
<HandleError(exceptiontype:=GetType(ArithmeticException),  Order:=50, View:="ProcessError")>
<HandleError()>
Public Class MathController

The problem is that, once ASP.NET MVC finds a HandleError attribute with a matching Exception, MVC ignores the other HandleError attributes, and the default HandleError matches every exception. The code may throw a DivideByZeroException, but if ASP.NET processes the default HandleError attribute (the one that doesn't specify a type) first, ASP.NET will never find the more specific HandleError for the DivideByZeroException. For this plan to work, therefore, I need ASP.NET MVC to process the HandleError attributes in a specific order, beginning with the attributes for the more specific exceptions and going on to the more general ones.

That's where the Order property on the HandleError attribute comes in: if you don't set the Order property, the HandleError attributes are processed in an undetermined order. If you do set the Order property, ASP.NET MVC will process the HandleError attribute with the highest number in the Order property first. Any HandleError attribute whose Order property isn't set is processed after the attributes with their Order property set.

In my example, by giving the HandleError attribute for the DivideByZeroException an Order property with the highest value, I've ensured that it's processed before the HandleError attribute for the ArithmeticException. By not setting the Order property on the default HandleError attribute, I ensure that it's processed only after the more specific HandleError attributes. Just what I want.

Posted by Peter Vogel on 04/04/2014 at 7:43 AM0 comments


Using the 'Map Mode' Scroll Bar in Visual Studio 2013

In Visual Studio 2013, right-clicking on the editor window's scroll bar and selecting Scroll Bar Options brings up a new option: "map mode for vertical scroll bar." The result is what you see in Figure 1: a wider scroll bar that shows your code in a compressed display.

[Click on image for larger view.] Figure 1. The optional wider scrollbar in Visual Studio 2013 gives you a high-level view of your code file with a "peek" capability.

Hovering your mouse over any part of the compressed code in the scroll bar gives you a preview of that part of the file. Clicking in the scroll bar moves you to that point in your code, instead of scrolling some arbitrary amount. And the bar still includes markers for errors and the caret (among other things), allowing you to jump to that part of your code by clicking on the marker.

I think that this feature is cool but, I've just started using it. And, besides, who cares what I think? If you're using Visual Studio 2013, try turning the feature on and leaving a comment about what you think.

Posted by Peter Vogel on 03/31/2014 at 7:16 AM0 comments


Free Tool: Entity Framework Power Tools

Regardless of what version of Entity Framework (EF) you're using, if you're doing code-first development, you should be looking at Microsoft's Entity Framework Power Tools, even if it is still in beta (Beta 4 appeared in October 2013 and added support for EF 6).

The beauty of code-first development is how easy it is to integrate your own code with the code required by EF. The problem with code-first EF development is the drudgery required to write all the code necessary to model your database. Power Tools goes a long way to eliminating that drudgery by writing the repetitive code for you -- all you have to do is install it through the Tools | Extension Manager menu choice.

To begin using the Power Tools, right-click on your project in Solution Explorer, select Entity Framework | Reverse Engineer Code First and you'll get the standard dialog for connecting to a database. Once you've connected to a database, Power Tools adds to your project the code for a DbContext class, plus the code for an entity class for each table in the database. Once you've generated that code, right-clicking on the file holding the DbContext class gives you access to more Power Tools magic. You should, for instance, be able to generate a read-only version of the database-first visual designer for your model.

I'd be lying if I didn't say that there are reasons that Power Tools is still in beta. Generating an entity class for every table is overkill (for any application I typically only need some of the tables in a database). I wish the Tools would let me use the configuration strings already set up in my project. And I'm not always able to generate the visual designer after generating my DbContext class.

If those “undocumented features” concern you (or you're just uncomfortable with using beta software), there's an alternative: You can use the latest version of EF's visual designer to generate your code.

Posted by Peter Vogel on 03/26/2014 at 7:18 AM0 comments


Defining Conversions for Visual Basic Classes

Sometimes you have to repeatedly convert one of your custom classes into something else. In Visual Basic, your conversions come in two types: Widening conversions and narrowing conversions. In a widening conversion, the new object holds all of the data of the original object: no errors can occur in this conversion and no data will ever be lost. In a narrowing conversion, the new object holds only some of the original object's data: some data may be lost and errors may occur.

As an example, consider three objects: a TypicalCustomer that holds the data that 80 percent of your customers require, a PremiumCustomer adds some more data to support additional functionality, and a DeadbeatCustomer (which has the least amount of functionality) that holds less data. Converting a TypicalCustomer to PremiumCustomer would be a widening operation, while converting a TypicalCustomer to a DeadbeatCustomer would be a narrowing conversion.

To add the code to convert a TypicalCustomer object to either a PremiumCustomer or a DeadbeatCustomer object, you add an Operator member (not a Function or Sub) to the class for each conversion. The member must be called CType, accept the object that you're converting from, and return the object you're converting to. The member must also be declared as Public Shared, and flagged as either Widening or Narrowing. The code to add to a TypicalCustomer class to support converting it to a PremiumCustomer or a DeadbeatCustomer would look like this:

Public Class TypicalCustomer
  Public Shared Widening Operator CType(ByVal Customer As TypicalCustomer) As PremiumCustomer
    Dim pc As New PremiumCustomer
    'transfer data from the Customer parameter to pc
    Return pc
  End Operator
  Public Shared Narrowing Operator CType(ByVal Customer As TypicalCustomer) As DeadbeatCustomer
    Dim dbc As New DeadbeatCustomer
    'transfer some of the data from the Customer parameter to dbc
    Return dbc
  End Operator
End Class

Your CType method is automatically invoked when the appropriate conversion is required. If your code has Option Strict Off, the difference between a widening and narrowing conversions doesn't matter, as in this example:

Dim tc As New TypicalCustomer
Dim pc As PremiumCustomer
Dim dbc As DeadbeatCustomer

pc = tc
dbc = tc

But if you're using Option Strict On, narrowing conversions can only be performed using Visual Basic's CType function, as in this example:

dbc = CType(cm, DeadbeatCustomer)

Posted by Peter Vogel on 03/13/2014 at 7:51 AM0 comments


Creating a Default Error Handler for a Controller

All you have to do to create a default error handler for your ASP.NET MVC controller is put the HandleError attribute on the class. Then, if your code throws an unhandled exception (one not caught in the Try…Catch block), the user will be sent the default Error View in the Views/Shared folder:

<HandleError>	
Public Class HomeController
        Inherits System.Web.Mvc.Controller

At least that's what the attribute will do if you have this tag inside the system.web element in your web.config file:

<customErrors mode="On" defaultRedirect="Error"/>

You can add whatever error information you want to the default Error View by adding code to the View that writes out properties from the Model's Exception property. Alternatively, setting the customErrors element's mode to RemoteOnly will, when you're debugging, let you continue to see ASP.NET's default error page with all of its information while still sending the Error View to your users in production.

Posted by Peter Vogel on 03/07/2014 at 9:37 AM0 comments


Visual Studio Tip: Delete a Line

I've written before about how to comment out code. Sometimes, however, you just want to get rid of a line altogether. The good news is that deleting a line is just a keystroke away, and you don't have to select the whole line to delete the whole line.

Instead, you can leverage the L (for "L"ine) key: <Ctrl>_L cuts the line the cursor is on so that you can paste the line in somewhere else. The more deadly <Shift>_<Ctrl>_L completely deletes the line, but if you need to get the line back, you can still use undo. And if you want to delete (or cut) multiple lines, just select multiple lines before using <Ctrl>_L or <Shift>_<Ctrl>_L, and you still don't have to select whole lines.

Posted by Peter Vogel on 03/05/2014 at 9:17 AM0 comments


Adding Your Own Explicit Type Conversions in C#

In my previous tip, I showed how to add an implicit conversion to C#. But there are two rules you should follow when defining an implicit conversion: 1) An implicit conversion should never throw an error, and 2) It should never lose information. If neither of those conditions is true, you should declare the conversion as explicit, as this code does:

public class PremiumCustomer
{
  public string CustomerId {get; set;}
  public string Name {get; set;}
  public bool CanUseCredit {get; set;}

  public static explicit operator PremiumCustomer(DeadbeatCustomer dbc)
  {
    PremiumCustomer pc = new PremiumCustomer();
    pc.CustomerId = dbc.CustomerId;
    pc.Name = dbc.Name;
    if (pc.CanUseCredit != true)
    {
      pc.CanUseCredit = dbc.CanUseCredit;
    }
    else
    {
      throw new Exception("Can't convert DeadbeatCustomers with bad credit");
    }
    return pc;
  }
}

The code to convert a DeadbeatCustomer to a PremiumCustomer would need an explicit cast and look, like this:

DeadbeatCustomer db = new DeadbeatCustomer();
PremiumCustomer pc = (PremiumCustomer) db;

Posted by Peter Vogel on 02/28/2014 at 9:28 AM0 comments


Adding Your Own Implicit Type Conversions in C#

You may find that you have two classes that you frequently need to convert between. You could repeat the conversion code wherever you need it, or put it in some random class. Or you could add a new implicit conversion to one of the classes.

For instance, if you need to frequently convert a DeadbeatCustomer into a PremiumCustomer, just put the code inside a conversion method in the PremiumCustomer class that accepts a DeadbeatCustomer. To add a conversion method to a class, first define a public static method, followed by the implicit keyword, the operator keyword, and the method's return type. The method must accept a parameter of the type you want to convert. Here's the code for the DeadbeatCustomer to PremiumCustomer conversion:

public class PremiumCustomer
{
  public string CustomerId {get; set;}
  public string Name {get; set;}
  public bool CanUseCredit {get; set;}

  public static implicit operator PremiumCustomer(DeadbeatCustomer dbc)
  {
    PremiumCustomer pc = new PremiumCustomer();
    pc.CustomerId = dbc.CustomerId;
    pc.Name = dbc.Name;
    pc.CanUseCredit = true;
    return pc;
  }
}

This code will automatically invoke your conversion method and handle the conversion:

DeadbeatCustomer db = new DeadbeatCustomer();
PremiumCustomer pc = db;

Be warned, though: I've made some assumptions here that I'll return to in my next tip.

Posted by Peter Vogel on 02/25/2014 at 6:44 AM0 comments


Upcoming Events

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.