Practical technique for dealing with null entities?

In my new ASP.NET EF4 project, I find myself having to do a lot of maneuvering around null entities. For example, I may have a Project Entity with a related User Entity exposed through an Assignee property. If, for example, I need to send an email to someone indicating who the Assignee is, I need to say:

string x = "The Assignee is: " + TheProject.Assignee.Name;

but I’ll get an exception if there is no Assignee as the property is null (I want nulls by design) and I can’t fetch the .Name property on that null. So I have to do this:

string x = "The Assignee is: " + TheProject.Assignee == null ? "", TheProject.Assignee.Name

This is tedious and messy, at best, and I find myself having to do it all over the place in my code. Has anyone come up with an elegant solution for this?

I also realize I can build a helper method, or an extension method (loving these!) but I’d have to hard code for the .Name property, which isn’t always what I want. I also want to avoid doing a whole bunch of reflection.

You could use the Null Coalescing Operator (??) like this:

string x = "The Assignee is: " + (TheProject.Assignee.Name ?? String.Empty);

Something like that.

That doesn’t work because TheProject.Assignee is null and you can’t call for it’s .Name property to do the null-check.

Oh, I see. I missed that.

How about using the ?? in the method that fills the .Name property? Then it’s handled all in one place.

It’s machine-generated by the Entity Framework and I’ve yet to discover any hooks where I can “get in”.

If you’re using EF4 you have a few options.

A) Use the Designers “Code Generation Item” menu option to generate a template, which you can alter and will be used to generate your entities and your context.

http://blogs.microsoft.co.il/blogs/gilf/archive/2009/12/05/t4-templates-in-entity-framework-4.aspx

B) Use the code-first option by turning off code generation altogether and just use POCO classes.

http://blogs.msdn.com/b/adonet/archive/2009/05/21/poco-in-the-entity-framework-part-1-the-experience.aspx

C) Upgrade to EF CTP5 (RTM very soon) and use a completely code based solution.

http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

Better option: model it with a bit of code. For example, if you need an assignee name from your Project class, why not make a method (or read only property) that encapsulates it:


public string AssigneeName {get { if (Employee == null) { return "NONE"; } return Employee.Name; }

Yeah. That’s what I was getting at. =) I think he’s using the designer though. You know, the one that pre-generates the code. So he can’t edit it and avoid having his changes overriden. That’s why I posted those options above. They would let him model it the way you suggest. Sorry I didn’t clarify.

Yup, well aware of that. There is a reason why there are partial classes in C# . . . .

lol…i’ve been working with NHibernate so long now, I’d forgotten about those. snicker

Well, I’d generally contend there are plenty of uses for partial classes beyond NH. We use them alot for big interface implementations and other things that would sully a class definition, for example.

Yeah, that’s not bad, I may try that one on for size. It makes one work a bit outside the entity model by crossing properties (because I’m making a property from the child show up in the parent) but it’s not too far out and about the same maintenance overhead as a helper method. I’ve frequently done that for things like concatenating Firstname and Lastname properties into a .Fullname property or making a password property writeonly and hashed.

On the contrary, this is quite typical of domain modelling.

Many proponents might even remove a public property for Assignee altogether. Making it a private member instead, and using a GetAssignee method that either returns the actual assignee or default(Assignee).

To further this, the Assignee class might not expose a Name property, using instead the same scenario as above to retrieve the Name, or some default value.

Assuming your Project class is the aggregate root, there would be the perfect place for this kind of domain method.