EntityObject Class Constructors

Did you know that the default classes generated by the Entity Framework Designer don't have class constructors? And that this is great news?

It means that you can create your own class constructors that will always be used when new entity objects are instantiated. This isn't limited to those times when you explicitly instantiate an object, but also when objects are being materialized from data returned by a query.

This is a great place to infer defaults that cannot be defined in the model itself. A perfect example of this is a default value for an Entity Reference navigation property. Although you can define defaults for an entity's scalar properties in the model, you cannot define defaults for navigation properties.

In my book's sample database, every Customer entity has a CustomerType. CustomerType can be Standard (1), Silver (2) or Gold (3). In the database, the CustomerTypeID foreign key is non-nullable and In the model, this is resolved as a 1:* relationship between CustomerType and Customer - meaning that every Customer must have a related CustomerType.

But the model has no way to define which CustomerType should be used by default.

Although EF will check this constraint when you call SaveChanges, it cannot be otherwise enforced without applying custom business logic.

One place you can insert this logic is in the SavingChanges method, just before the commands are sent to the database. But what if you don't want to wait until that point? More likely, you'll want that default CustomerType to be defined any time a new customer is created in memory.

Enter, the constructor. Because it is not yet defined, you can create a default constructor in the partial class for the entity.

public partial class Customer
  {
    public Customer()
    {
      this.CustomerTypeReference.EntityKey =
           new EntityKey("EFEntities.CustomerTypes", "TypeID", 1);
    }
}

Partial Public Class Customer
    Public Sub New()
      CustomerTypeReference.EntityKey = _
          New EntityKey("EFEntities.CustomerTypes", "TypeID", 1)
    End Sub
End Class

This constructor will be used for objects coming from the database as well those which you instantiate in code. In the case of the objects materialized from the database, this default will be overwritten by the incoming value, e.g., the actual CustomerType of the Customer coming from the data store. However,  in this case, the object's EntityState will remain Unchanged. So you don't have to worry about it screwing up data coming from the database when applying this default.

#1 john on 1.12.2010 at 9:00 AM

OMG, this is what I am looking for. I wasted 5 hours looking for this.

One question. How do I reference this Entity Key? I tried:

String x = Customer.EntityKey.EntityKeyValues.ToString(); and it didnt work :(

Thanks

#2 Julie on 1.12.2010 at 3:06 PM

@John

EntityKey is a set of keyvalue pairs. SO EntityKeyValues returns and array of keyvalues pairs, not a string.

Therefore, presueming that you only have one KVP in there, e.g. contact entity has only one property, contactId marked as EntityKey, then you just need to read the FIRST KVP.

EntityKey.EntityKeyValues(0)

From there you can get either a key or a value. Key would be e.g. "ContactID" while value would be the actual property value.

So:

EntityKey.EntityKeyValues(0).Value.ToString()

hth

julie

#3 john on 1.12.2010 at 6:50 PM

thanks julie.

using your reference i tried:

int x = (int)x.CustomerReference.EntityKey.EntityKeyValues[0].Value;

it kinda works. however it always return whatever value i set in the constructor.

for example:

public Customer()

{

this.CustomerReference.EntityKey = new EntityKey("EFEntities.CustomerTypes", "TypeID", 999);

}

and the result is x == 999. it doesn’t override the default value???

#4 Julie on 1.12.2010 at 7:01 PM

Hi John

I'll assume that there's a typo there and you are setting CustomerTypeReference.EntityKey.

If you create a new customer in memory, it will get that FK value (999). I fyou retrieve entities from the database, you should be getting the customertypeid value that was the FK value in the database. THe order of events is that as the data is returned from the db, a new customer is created with the default values (from constructor or from model) and then all of the values are overwritten with teh db data.

So I don't really know WHERE you are checking the value of the entitykey value and always getting 999.

julie

#5 john on 1.12.2010 at 7:28 PM

thanks got it now!

#6 Julie on 1.12.2010 at 7:34 PM

yay

By the way - you get FKs in EF4. No more futzing around with entitykeys. :)

Leave a Comment