Monday, February 20, 2012 » .net c# entity-framework

EF 4.1 - Loading related Entities on type mismatch

While working with Entity Framework has improved quite a bit since it’s first release, sometimes I still encounter some behaviors that are rather strange. Consider the following model. A simple one-to-many relationship. One item can be in many reports.

[Table("Items")]
class Item
{
    [Key, StringLength(16)]
    public string Itemcode { get; set; }

    [Required, StringLength(30)]
    public string Description { get; set; }

    // ...
}

[Table("Reports")]
class Report
{
    [Key]
    public int Id { get; set; }

    public string Itemcode { get; set; }
    [ForeignKey("Itemcode")]
    public virtual Item Item { get; set; }

    // ...
}

I build a model similar to that against a legacy database. The Item table had a primary key of type char(16). The report tables Itemcode column was of type varchar(17) and no real relationship (in sql terms). The types don’t match. What’s interesting though is that the model still partially works. The following query runs perfectly fine:

var reports = (from x in context.Reports 
                select new { 
                    x.Id,
                    x.Item.Itemcode,
                    x.Item.Description }
            ).ToList();

In this case Entity Framework doesn’t really care about the mismatching types and joins them anyway. After all it works in SQL too. So far so good, but guess what happens if we write something like this:

var report = context.Reports.Include(x => x.Item).Single(x => x.Id == 1234);
Console.WriteLine(report.Item.Description);

Chances are that you’ll be greeted by a beautiful NullReferenceException. We’re out of luck. report.Item is null. What’s rather odd is that the SQL generated is correct (at least LINQPad shows the correct SQL) and the ItemReference.IsLoaded Property is true.

Still, there is no way (that I know of) to get Entity Framework to properly load that related entity. (Other than fixing the database model and make the types match each other. And you should do that anyway).