This article is Part 2 of 3 – please see http://blogs.msdn.com/adonet/archive/2008/07/21/update-model-a-question-of-identity-part-1-of-3.aspx for Part 1.
In the last article I explained the principle that the C-side updates would be non-destructive.
The “Update Model” code needs to decide when we should add new C-side EntityTypes, new C-side Properties and new C-side Associations. This brings us into the idea of identity. Bear with me – this can get pretty complicated.
Suppose you have a database with two tables in it. They have the same name but are in different schemas e.g. schema1.Customer and schema2.Customer. All S-side EntitySets (which are the way the EDM represents a database table or view) in a given model must have unique names. So if you attempt to import both of the above tables then one of them will be represented as an EntitySet with name ‘Customer’ and one with name ‘Customer1’ each with a matching EntityType. Which one will be which? Well, it depends on in what order you import them and sometimes on what else you import at the same time. The important point is that the Name attribute of the EntitySet is not always the same as the name of underlying database object.
So we cannot rely on the Name attribute of a given EntitySet to identify the underlying database object. But for “Update Model from Database” we do need to identify what the true underlying database object is to decide whether a given one is “new”. So instead we construct a “database identity” for each S-side EntitySet which consists of its underlying schema name and its underlying table/view name. If the EntitySet’s Name attribute does not match the underlying table/view name then either a Table attribute or the special attribute store:Name (where ‘store’ is a prefix defined as the XML namespace “http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator”) is defined on that EntitySet. The value of this attribute is the true underlying database object name. Similarly the Schema or store schema attribute will represent the true underlying database schema name (and there’s a similar story for Function elements which is how the EDM represents stored procedures).
This combination of the true database schema name and the true database object name are the “database identity” of that EntitySet. “New” S-side EntitySets are defined as those whose “database identity” does not appear in the S-side of the existing model.
For every imported, new S-side EntitySet we create a single, matching C-side EntitySet and EntityType and the mappings necessary to map them through to the S-side EntitySet. If it is available, we will use the existing S-side name for the matching C-side EntityType, but that name may already be in use in which case we will try appending 1, 2, 3 … until we find a name that is not in use.
So as an example, if a C-side EntityType, say ‘Customer’, was originally mapped to the S-side ‘Customer’ EntityType but has been manually unmapped, and “Update Model from Database” is run then the above rules will _not_ result in a “duplicate” C-side EntityType called ‘Customer1’ because “Update Model” knows that there was already a ‘Customer’ S-side EntityType – we assume the user knew what s/he was doing when they unmapped the C-side EntityType. However if a _new_ S-side EntityType called ‘Customer’ is added and there happens to exist a C-side EntitySet already called ‘Customer’ then the new, matching C-side EntityType would be called ‘Customer1’ and it will be up to the user to rename the C-side EntityTypes as needed.
In the next article I’ll explain how this concept is extended to C-side Properties and Associations.
Software Design Engineer, Entity Framework Tools