Entity Framework FAQ: EntityKey
[[articles:Entity Framework FAQ|Back to EF FAQs Table of Contents]]
Yes! The flow of a typical new entity with a server-generated key value looks something like this:
- Construct the entity instance. At this point the key properties all have default values (null or 0).
- Add the instance to your context. A temporary key is created and used to store the entity in the ObjectStateManager.
- Call SaveChanges on the context. The EF computes a SQL insert statement (or a stored procedure invocation if so-specified in the mapping) and executes it.
- EF writes the server-generated value back to the ObjectStateEntry for the entity. This assumes, of course, that the insert succeeded and that the SSDL was properly configured to indicate that there is a server-generated value. Fortunately, if the SSDL is generated from the database schema by a tool, this configuration is automatically done as part of that generation.
- The ObjectStateEntry pushes the server-generated value into the entity itself. The EF's lower level code uses the DataRecord interface on the ObjectStateEntry to read and write values from the entity. The ObjectStateEntry guarantees that the entity object and the DataRecord interface always contain the same data (for current values the DataRecord, in fact, is virtualized over the entity rather than storing its own copy of the data).
- When AcceptChanges is called on the ObjectStateEntry, a permanent EntityKey is computed using the new, unique property key values. The ObjectStateManager then does an internal fixup, replacing all instances of the temporary key with the new permanent key.
To configure the EF for a server-generated key value, you just need the StoreGeneratedPattern attribute to be set on the database column in the SSDL. For a key it should typically be set to "Identity", which means the value will be generated when the row is inserted but will not change after that. For other server-generated properties you might want to use the value "Computed", which means that it will change every time the row is updated.
Can I create a new entity with a server-generated key and a set of related new entities that have a foreign key to that entity in a single update?
Yes. You can create arbitrarily complex graphs of entities with server-generated values and the system can handle inserts of those entire graphs in a single call to SaveChanges.
Yes. You can use a GUID in your conceptual model as a regular property or a primary key.
There is, however, a limitation that the EF does not support primary keys whose type is binary. What this means in practice is that if your database has a column of type "uniqueidentifier", then the automatic model generation will recognize that it contains a GUID and configure the corresponding property in the conceptual model to be a GUID, but if your column in the database is of type binary with a length of 16 bytes, then the automatic model generation will make the type of the property in the conceptual model a byte array of length 16, and that cannot be the primary key for your entity.
If you go into the designer, you can manually modify the type of the conceptual model property to be a GUID rather than a byte array, and then the property can be the entity key for that type. At that point, you will receive errors from the mapping system saying that it can't map a GUID onto a 16-byte binary. To fix that you will need to open the EDMX file in the XML editor (or edit your SSDL file if you are not using the designer) and change the metadata for the column in your database to claim that it is a uniqueidentifier rather than a 16-byte binary. After all of this is done, the EF will identify the column as a uniqueidentifier, which maps nicely to a GUID.
It is supported in EF 4. For more information, see Working with Entity Keys.
In EF 3.5 SP1 this is not supported. While it is possible for SQL Server to have a column of type `uniqueidentifier` and to set its default value to be `newid()`, with SQL Server 2000 there's no good way to extract the value that the server generated at the time you do the insert.
Yes, you can. There is one thing to keep in mind, though: The default GUID generation scheme creates GUIDs, which can make for very inefficient indexes in the database. Wherever possible it is recommended to use a server-generated integer or something similar for the key properties of an entity.
The following links have information related to this issue:
- Working with EntityKeys
- Tip 20 How to Deal with Fixed Length Keys
- EF 4 - POCO - Trimming properties for entities
[[articles:Entity Framework FAQ|Back to EF FAQs Table of Contents]]