Using a Complex Type in Entity Framework vs. Creating a New Entity

.net .net-4.0 c# entity-framework


I'm reading about the Entity Framework 4.0 and I was wondering why should I create a complex type and not a new Entity (Table) and a relation between them?

4/9/2011 7:12:59 PM

Accepted Answer

The perfect example is an address. Using a complex type for an address is much easier to deal with than a new entity. With complex types you do not have to deal with the Primary Key. Think about accessing an address how many common types of entities would have an address (Business Units, People, Places). Imagine populating many peoples addresses and needing to set a key for each one. With complex types you simply access the internal properties of they type and you're done. Here is an MSDN link of an example.

1/30/2014 8:57:14 PM

Popular Answer

This question has been here a while already, but I'm going to add an answer anyway in the hopes that the next poor sob that comes along knows what he's in for.

Complex types do not support lazy loading, at least not in EF 4.3. Let's take the address situation as an example. You have a Person table with 15 columns, 5 of which contain address information for certain individuals. It has 50k records. You create entity Person for the table with a complex type Address.

If you need a list of names of all individuals in your database you would do

var records = context.Persons;

which also includes addresses, pumping 5*50k values into your list for no reason and with noticeable delay. You could opt to only load the values you need in an anonymous type with

var records = from p in context.Persons
              select new {
                LastName = p.LastName,
                FirstName = p.FirstName,

which works well for this case, but if you needed a more comprehensive list with, say, 8 non-address columns you would either need to add each one in the anonymous type or just go with the first case and go back to loading useless address data.

Here's the thing about anonymous types: While they are very useful within a single method, they force you to use dynamic variables elsewhere in your class or class children, which negate some of Visual Studio's refactoring facilities and leave you open to run-time errors. Ideally you want to circulate entities among your methods, so those entities should carry as little baggage as possible. This is why lazy loading is so important.

When it comes to the above example, the address information should really be in a table of its own with a full blown entity covering it. As a side benefit, if your client asks for a second address for a person, you can add it to your model by simply adding an extra Address reference in Person.

If unlike the above example you actually need the address data in almost every query you make and really want to have those fields in the Person table, then simply add them to the Person entity. You won't have the neat Address prefix any more, but it's not exactly something to lose sleep over.

But wait, there's more!

Complex types are a special case, a bump on the smooth landscape of plain EF entities. The ones in your project may not be eligible to inherit from your entity base class, making it impossible to put them through methods dealing with your entities in general.

Assume that you have an entity base class named EntityModel which defines a property ID. This is the key for all your entity objects, so you can now create

class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel

which you then can use with Distinct() to filter duplicates from any IQueryable of type T where T is an entity class. A complex type can't inherit from EntityModel because it doesn't have an ID property, but that's fine because you wouldn't be using distinct on it anyway.

Further down the line you come across a situation where you need some way to go through any entity and perform an operation. Maybe you want to dynamically list the properties of an entity on the UI and let the user perform queries on them. So you build a class that you can instantiate for a particular type and have it take care of the whole thing:

public class GenericModelFilter<T> : where T : EntityModel

Oh wait, your complex type is not of type EntityModel. Now you have to complicate your entity inheritance tree to accommodate complex types or get rid of the EntityModel contract and reduce visibility.

Moving along, you add a method to your class that based on user selections can create an expression that you can use with linq to filter any entity class

Expression<Func<T, bool>> GetPredicate() { ... }

so now you can do something like this:

personFilter = new GenericModelFilter<Person>();
companyFilter = new GenericModelFilter<Company>();
addressFilter = new GenericModelFilter<Address>(); //Complex type for Person


var query = from p in context.Persons.Where(personFilter.GetPredicate())
            join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID
            select p;

This works the same for all entity objects... except Address with its special needs. You can't do a join for it like you did with Company. You can navigate to it from Person, but how do you apply that Expression on it and still end up with Person at the end? Now you have to take moment and figure out this special case for a simple system that works easily everywhere else.

This pattern repeats itself throughout the lifetime of a project. Do I speak from experience? I wish I didn't. Complex types keep stopping your progress, like a misbehaved student at the back of the class, without adding anything of essence. Do yourself a favor and opt for actual entity objects instead.

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow