Udostępnij za pośrednictwem


Working with Entity Keys

Each entity type has a key that is based on one or more scalar properties of the entity. Keys are defined by the Key element in the conceptual model. As in relational databases, these key values are used to verify the uniqueness of a given entity and to improve the performance of queries. Usually, key properties are mapped to a key column in the underlying table, either an identity column or some other column that is constrained to guarantee a unique value. For more information about how keys are defined in the conceptual model, see Key Element (CSDL).

When an object is returned by an object query, the Entity Framework materializes the entity object. It also materializes the entity key into an instance of the EntityKey class. You can access this EntityKey from the EntityKey property of an object that implements IEntityWithKeyEntityObject, which is the base class for all data classes generated by the Entity Data Model tools, also implements IEntityWithKey.

Note

The Entity Framework does not require you to implement IEntityWithKey in a custom data class.

Constructing and Using an EntityKey Object

An EntityKey object is composed of EntitySetName and EntityContainerName properties and an array of one or more key/value pairs. A key/value pair consists of a property name and property value. You supply key/value pairs as one or more EntityKeyMember objects in the EntityKeyValues property.

Note

When you use one of the EntityKey constructors, the string value supplied to the qualifiedEntitySetName parameter is the EntitySetName pre-pended by the EntityContainerName, as in "EntityContainerName.EntitySetName".

You can also use the CreateEntityKey method on ObjectContext to get the EntityKey for a detached object. If the object does not have a valid key, the object context constructs a new EntityKey instance for the specified object. For more information, see How to: Create an EntityKey.

Because an entity key uniquely identifies an entity, you can create an entity with just the key and attach the object to an object context, even if the remaining object values were not retrieved from the data source. For more information, see How to: Attach Related Objects. An entity key can also be used to retrieve an object from either the object context or from the data source. For more information, see How to: Return a Specific Object Using its Key.

Fixed Length Entity Keys

The Entity Framework performs identity resolution based on the value of the EntityKey, which corresponds to a primary key in the database. If a query returns an object with an EntityKey that already exists in the ObjectContext, a new object is not created. If you are working with fixed size columns in the database and are persisting values that are shorter than the size specified in the database, some databases will pad fixed-size types with spaces or zeros. SQL Server pads fixed-size string types with trailing spaces. When fixed-size types (such as binary, or char) are used as primary keys, it could result in identity resolution problems. 

Consider the following example. The Product table has a fixed-length column of size 10 for the primary key. A Product object with EntityKey AB100 is created and added to the ObjectContext. When the object is saved to the database, the key is padded with trailing spaces because the column is of a fixed size and the saved value is shorter than the size in the database. A subsequent query for an object with an EntityKey of AB100 will return an object with a different EntityKey (AB100 followed by trailing spaces) because SQL Server matches AB100 to the padded string. The Entity Framework does not trim or pad the values of properties. The result is that a new object (with EntityKey AB100 followed by trailing spaces) is added to the ObjectContext

Product p1= new Product 
{ 
    ProductID = "AB100", 
    Description = "New product" 
}; 
// An object with EntityKey "AB100" is added to ObjectContext.
ctx.Products.AddObject(p1); 
// The object is saved in the database with a primary key of 
// "AB100     " because the column is of a fixed size.
ctx.SaveChanges();
// When a query is executed for an object with key "AB100", SQL Server // matches the key to "AB100     ". The result is that a new object 
// with EntityKey "AB100     " is added to ObjectContext.
Product p2 = ctx.Products.First(p => p.ProductCode == "AB100");

To avoid this undesirable behavior, you can do one of the following:

  • Use a variable length type instead of a fixed length type in the database.

  • Pad the value of the EntityKey with trailing spaces or zeros on the client. You can use PadRight method to pad a string with spaces.

Entity Keys and Added Objects

When a new entity is created, the Entity Framework defines temporary key and sets the IsTemporary property to true. When you call the SaveChanges method, the Entity Framework assigns a permanent key and sets the IsTemporary property to false.

If the corresponding column value is an identity that is generated in the database, set the StoreGeneratedPattern attribute of the Property element of an entity in the storage model to Identity. When the Entity Data Model tools generate a data model from an existing data source, the StoreGeneratedPattern attribute is added to each Property Element (CSDL) element that represents an identity or a computed column in the data source. The Entity Framework replaces the value of the property in a temporary key with the identity value that is generated by the data source after SaveChanges is called.

The following details the internal process that replaces the temporary key with a permanent key that contains the server-generated values:

  1. The entity object is constructed.

    At this point the key properties all have default values, either null or 0.

  2. The new object is added to the ObjectContext either by calling the AddObject method on ObjectContext or ObjectSet or by adding an object to the collection of objects on the "many" end of the relationship.

    At this point, the Entity Framework generates a temporary key, which is used to store the objects in the ObjectStateManager.

  3. SaveChanges is called on the ObjectContext.

    An INSERT statement is generated by the Entity Framework and executed on the data source.

  4. If the INSERT operation succeeds, server-generated values are written back to the ObjectStateEntry.

  5. The ObjectStateEntry updates the object with the server-generated value.

  6. When AcceptChanges is called on the ObjectStateEntry, a permanent EntityKey is computed by using the new server-generated values.

    Note

    AcceptChanges is called automatically at the end of the SaveChanges execution, or when the SaveChanges method is called with the AcceptAllChangesAfterSave flag.

  7. The ObjectStateManager replaces all instances of the temporary key with the new permanent key.

GUID Property Values

The Entity Framework supports entity properties that return a Guid type to ensure uniqueness.

The Entity Framework supports server-generated GUID type identity values, but the provider must be able to return the server-generated identity value after a row is inserted. SQL Server can return the server-generated GUID type through the OUTPUT clause starting with SQL Server 2005. If a provider does not support the equivalent of the OUTPUT clause, generate GUID values for new objects on the client. To do this, we recommend handling the SavingChanges event to generate a new GUID value for any entity object in the Added state. For more information, see How to: Execute Business Logic When Saving Changes.

When you generate or update a data model with the Entity Data Model Wizard or the Update Model Wizard, GUID properties of entity types are automatically generated for uniqueidentifier-typed columns in the data source. A data source may also use 16-byte binary columns to store GUID values. Because the tools generate a binary property for each binary column in the data source, you must manually update the mapping of such columns to GUID properties by editing the .edmx file. For more information, see How to: Map a GUID Property to a Binary Column.

In This Section

How to: Create an EntityKey

See Also

Tasks

How to: Create an EntityKey

Other Resources

Entity Data Model Tools